RealtimeCompLab2
Dependencies: mbed
Fork of PPP-Blinky by
Diff: main.cpp
- Revision:
- 77:abf92baebb42
- Parent:
- 76:00e208cceb8b
- Child:
- 78:809c2631a5eb
--- a/main.cpp Wed Jul 05 20:05:42 2017 +0000 +++ b/main.cpp Sat Jul 08 10:10:12 2017 +0000 @@ -42,6 +42,8 @@ #define v0 1 // verbosity flag used in debug printouts - change to 0 to see less debug info. Lots of interesting info. #define v1 1 +// verbosity flag used in debug printouts - change to 0 to see less debug info. Lots of interesting info. +#define v2 0 // this is the webpage we serve when we get an HTTP request // keep size under 900 bytes to fit into a single frame @@ -97,7 +99,8 @@ int len; // number of bytes in buffer int crc; // PPP CRC (frame check) //char * buf; // the actual buffer - char buf[3300]; // send and receive buffer large enough for unstuffed (decoded) hdlc frames +#define TCP_max_size 3300 + char buf[TCP_max_size]; // send and receive buffer large enough for unstuffed (decoded) hdlc frames } pkt; // ppp buffer objects struct { int frameStartIndex; // frame start marker @@ -333,7 +336,7 @@ unsigned int dataCheckSum(unsigned char * ptr, int len) { - + unsigned int sum=0; unsigned char placeHolder; if (len&1) { @@ -394,7 +397,7 @@ int icmpIdent = (icmpType[4]<<8)|icmpType[5]; int icmpSequence = (icmpType[6]<<8)|icmpType[7]; #endif - debug("ICMP PING %d.%d.%d.d %d.%d.%d.%d ", srcAdr[0],srcAdr[1],srcAdr[2],srcAdr[3],dstAdr[0],dstAdr[1],dstAdr[2],dstAdr[3]); + debug("ICMP PING %d.%d.%d.%d %d.%d.%d.%d ", srcAdr[0],srcAdr[1],srcAdr[2],srcAdr[3],dstAdr[0],dstAdr[1],dstAdr[2],dstAdr[3]); debug("Ident %04x Sequence %04d ",icmpIdent,icmpSequence); char src[4]; char dst[4]; @@ -458,7 +461,7 @@ char * flags = ipPkt+6; // 2 bits char * ttl = ipPkt+8; // 1 byte char * protocol = ipPkt+9; // 1 byte - unsigned char * headercheck= ipPkt+10; // 2 bytes + char * headercheck= ipPkt+10; // 2 bytes #endif char * srcAdr = ipPkt+12; // 4 bytes char * dstAdr = ipPkt+16; // 4 bytes = total of 20 bytes @@ -512,14 +515,16 @@ if (flags & (1<<6)) flagInfo[6]='E'; if (flags & (1<<7)) flagInfo[7]='C'; if (flags & (1<<8)) flagInfo[8]='N'; - if (v0) { - debug("Flags %s Seq %u Ack %u", flagInfo, seq, ack); // show the flags in debug + if (v1) { + debug("Flags %s Seq %u Ack %u\n", flagInfo, seq, ack); // show the flags in debug } } int httpResponse(char * dataStart) { int n=0; // number of bytes we have printed so far + int nHeader; // byte size of HTTP header + if(strncmp(dataStart, "GET / HTTP/1.1", 14) == 0 ) { n=n+sprintf(n+dataStart,"HTTP/1.1 200 OK\r\nServer: PPP-Blinky\r\n"); // http header n=n+sprintf(n+dataStart,"Content-Length: "); // http header @@ -527,8 +532,7 @@ n=n+sprintf(n+dataStart,"?????\r\n"); // leave five spaces for content length - will be updated later n=n+sprintf(n+dataStart,"Connection: close\r\n"); // close connection immediately n=n+sprintf(n+dataStart,"Content-Type: text/html; charset=us-ascii\r\n\r\n"); // http header must end with empty line (\r\n) - int nHeader=n; // byte size of the HTTP header. Note - seems like this must be 1+(multiple of four) - + nHeader=n; // size of HTTP header // this is where we insert our web page into the buffer n=n+sprintf(n+dataStart,"%s\r\n", ourWebPage); @@ -537,9 +541,6 @@ snprintf(contentLengthString,CONTENTLENGTHSIZE+1,"%*d",CONTENTLENGTHSIZE,n-nHeader); // print Content-Length with leading spaces and fixed width equal to csize memcpy(dataStart+contentLengthStart, contentLengthString, CONTENTLENGTHSIZE); // copy Content-Length to it's place in the send buffer - if (v0) { - debug("HTTP GET BufferSize %d*32=%d Header %d Content-Length %d Total %d Available %d\n",dataLen/32,dataLen,nHeader,contentLength,n,dataLen-n); - } } else { // all remaining requests get 404 Not Found response and heap size n=n+sprintf(n+dataStart,"HTTP/1.1 404 Not Found\r\nServer: PPP-Blinky\r\n"); // http header n=n+sprintf(n+dataStart,"Content-Length: "); // http header @@ -547,7 +548,7 @@ n=n+sprintf(n+dataStart,"?????\r\n"); // leave five spaces for content length - will be updated later n=n+sprintf(n+dataStart,"Connection: close\r\n"); // close connection immediately n=n+sprintf(n+dataStart,"Content-Type: text/html; charset=us-ascii\r\n\r\n"); // http header must end with empty line (\r\n) - int nHeader=n; // byte total of all headers. Note - seems like this must be 1+(multiple of four) + nHeader=n; // size of HTTP header n=n+sprintf(n+dataStart,"<!DOCTYPE html><html><head></head>"); // html start n=n+sprintf(n+dataStart,"<body><h1>File Not Found. Stack=0x%08x</h1></body>",&nHeader); @@ -556,11 +557,11 @@ char contentLengthString[CONTENTLENGTHSIZE+1]; // temporary buffer to create Content-Length string snprintf(contentLengthString,CONTENTLENGTHSIZE+1,"%*d",CONTENTLENGTHSIZE,n-nHeader); // print Content-Length with leading spaces and fixed width equal to csize memcpy(dataStart+contentLengthStart, contentLengthString, CONTENTLENGTHSIZE); // copy Content-Length to it's place in the send buffer + } + if (v2) { + debug("HTTP Response: HTTP-header %d HTTP-content %d HTTP-total %d\n",nHeader,n-nHeader,n); + } - if (v0) { - debug("HTTP GET BufSize %d*32=%d Header %d Content-Length %d Total %d Available %d\n",dataLen/32,dataLen,nHeader,contentLength,n,dataLen-n); - } - } return n; // total byte size of our response } @@ -594,13 +595,13 @@ int headerSizeTCP = ((offset[0]>>4)&0x0f)*4; // size of tcp header only int protocolIP = protocol[0]; - unsigned int seq = (seqtcp[0]<<24)|(seqtcp[1]<<16)|(seqtcp[2]<<8)|(seqtcp[3]); - unsigned int ack = (acktcp[0]<<24)|(acktcp[1]<<16)|(acktcp[2]<<8)|(acktcp[3]); - int flagsTCP = ((flagbitstcp[0]&1)<<8)|flagbitstcp[1]; char * dataStart = ppp.pkt.buf + 4 + headerSizeIP + headerSizeTCP; // start of data block after TCP header int tcpDataSize = tcpSize - headerSizeTCP; // size of data block after TCP header + + unsigned int ack = (seqtcp[0]<<24)|(seqtcp[1]<<16)|(seqtcp[2]<<8)|(seqtcp[3]) + tcpDataSize; + unsigned int seq = (acktcp[0]<<24)|(acktcp[1]<<16)|(acktcp[2]<<8)|(acktcp[3]); #define TCP_FLAG_ACK (1<<4) #define TCP_FLAG_SYN (1<<1) @@ -612,39 +613,37 @@ 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 - ppp.seq = ack; // always adopt their sequence number calculation in place of doing our own calculation - // 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 // This strategy allows web browsers, netcat and curl to work ok while keeping the state machine simple - + switch ( flagsTCP ) { case TCP_FLAG_ACK: if ( tcpDataSize != 1 ) return; case TCP_FLAG_SYN: flagsOut = TCP_FLAG_SYN | TCP_FLAG_ACK; // something wants to connect - ack it - seq++; // for SYN flag we have to increase sequence by 1 + ack++; // for SYN flag we have to increase sequence by 1 break; - case TCP_FLAG_ACK | TCP_FLAG_PSH: + 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 + dataLen++; // must be a multiple of four + dataStart[dataLen-1]=0; // clear the byte in the buffer } } break; - case TCP_FLAG_FIN: + case TCP_FLAG_FIN: case TCP_FLAG_FIN | TCP_FLAG_ACK: case TCP_FLAG_FIN | TCP_FLAG_ACK | TCP_FLAG_PSH: - seq++; // for FIN flag we have to increase sequence by 1 + ack++; // for FIN flag we have to increase sequence by 1 break; - default: + default: return; // ignore remaining packets } - + // 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 @@ -657,9 +656,6 @@ memcpy(srctcp, dsttcp,2); memcpy(dsttcp, tempHold,2); // swap ip port source/dest - ack = seq + tcpDataSize; // acknowledge the number of data bytes that they sent by adding it to "our" sequence number - seq = ppp.seq; // set up the sequence number we have to respond with - acktcp[0]=ack>>24; acktcp[1]=ack>>16; acktcp[2]=ack>>8; @@ -709,10 +705,9 @@ } else { // normally, you wait 200 ms before sending a TCP packet // remove the wait to respond faster - // wait(0.2); + wait(0.05); } sendFrame(); // All done! Send the TCP packet - ppp.seq = ppp.seq + dataLen; // increase OUR sequence by the outgoing data length - for the next round } void dumpDataTCP() @@ -770,8 +765,13 @@ if (v0) { debug("i%04x f%d t%d p%d C%04x\n",identIP,flagsIP,ttlIP,protocolIP,checksumIP); } - dumpHeaderTCP(); - dumpDataTCP(); + if (v1) { + dumpHeaderTCP(); + } + + if (v2) { + dumpDataTCP(); + } tcpHandler(); } @@ -919,11 +919,11 @@ { if ( ppp.online==0 ) { // look for Windows Dialup Networking "Direct Connection Between Two Computers" expected connect string - char * clientFound = strstr( (char *)ppp.rx.buf, "CLIENTCLIENT" ); + char * clientFound = strstr( (char *)ppp.rx.buf, "CLIENTCLIENT" ); if( clientFound ) { strcpy( clientFound, "FOUND!FOUND!" ); // overwrite so we don't find it again // respond with Windows Dialup networking expected "Direct Connection Between Two Computers" response string - pc.printf("CLIENTSERVER"); + pc.printf("CLIENTSERVER"); ppp.online=1; // we are connected, so stop looking for the string debug("Connect string found\n"); }