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: PPP-Blinky/ppp-blinky.cpp
- Revision:
- 146:a45f49a2b29c
- Parent:
- 145:098b6ed2f7f2
- Child:
- 147:0f40005cbc5f
--- a/PPP-Blinky/ppp-blinky.cpp Tue Aug 29 18:57:04 2017 +0000 +++ b/PPP-Blinky/ppp-blinky.cpp Wed Aug 30 00:55:21 2017 +0000 @@ -32,7 +32,7 @@ // Special pages when PPP-Blinky is running // 172.10.10.2 root page // 172.10.10.2/x returns a number that increments every time you request a page - this is handy for testing -// 172.10.10.2/xb also returns a number, but issues a fast refresh command. This allows you to use your browser to benchmark page load speed +// 172.10.10.2/xb also returns a number, but issues a fast refresh meta command. This allows you to use your browser to benchmark page load speed // 172.10.10.2/ws a simple WebSocket demo // http://jsfiddle.net/d26cyuh2/ more complete WebSocket demo in JSFiddle @@ -41,9 +41,10 @@ #include "ppp-blinky.h" // The #define below enables/disables a second (OPTIONAL) serial port that prints out interesting diagnostic messages. -// Change to SERIAL_PORT_MONITOR_YES to enable diagnostics messages. You need to wire a second serial port to your mbed hardware to monitor this. +// Change to SERIAL_PORT_MONITOR_YES to enable diagnostics messages. You need to wire a second serial port to your mbed hardware to monitor the debug output. // Using the second serial port will slow down packet response time // Note - the LPC11U24 does NOT have a second serial port + #define SERIAL_PORT_MONITOR_NO /* change to SERIAL_PORT_MONITOR_YES for debug messages */ // here we define the OPTIONAL, second debug serial port for various mbed target boards @@ -86,12 +87,12 @@ <!DOCTYPE html>\ <html>\ <head>\ -<title>mbed PPP-Blinky</title>\ -<script>\ +<title>mbed PPP-Blinky</title>\r\n\ +<script>\r\n\ window.onload=function(){\ setInterval(function(){function x(){return document.getElementById('w');};\ -x().textContent=parseInt(x().textContent)+1;},100);};\ -</script>\ +x().textContent=parseInt(x().textContent)+1;},100);};\r\n\ +</script>\r\n\ </head>\ <body style=\"font-family: sans-serif; font-size:20px; text-align:center; color:#807070\">\ <h1>mbed PPP-Blinky Up and Running</h1>\ @@ -102,7 +103,7 @@ <h1><a href=\"/xb\">Benchmark 2</a></h1>\ <h1><a href=\"http://jsfiddle.net/d26cyuh2/\">JSFiddle Demo</a></h1>\ </body>\ -</html>"; // size = 634 bytes plus 1 null byte = 635 bytes +</html>\r\n"; // size = 644 bytes plus 1 null byte = 645 bytes const static char webSocketPage[] = "\ <!DOCTYPE html>\ @@ -159,7 +160,7 @@ int hostIP; // ip address of host int fcs; // PPP "frame check sequence" - a 16-bit HDLC-like checksum used in all PPP frames int ledState; // state of LED1 - int httpPageCount; + int responseCounter; int firstFrame; // cleared after first frame struct { #define RXBUFLEN (1<<11) @@ -201,7 +202,7 @@ ppp.ip.ident=10000; // easy to recognize in ip packet dumps ppp.ledState=0; ppp.hdlc.frameStartIndex=0; - ppp.httpPageCount=0; + ppp.responseCounter=0; ppp.firstFrame=1; } @@ -264,12 +265,6 @@ #endif } -/// a sniffer tool to assist in figuring out where in the code we are having characters in the input buffer -void qq() -{ - if ( pc.readable() ) putsWhileCheckingInput( "Character available!\n" ); -} - /// Initialize the PPP FCS (frame check sequence) total void fcsReset() { @@ -442,12 +437,14 @@ /// This is how Linux responds to an IPCP request with no options - Windows assumes any IP address on the submnet is OK. void ipcpNackHandler() { - debugPrintf("Their IPCP Nack"); + debugPrintf("Their IPCP Nack\n"); if (ppp.pkt.buf[8]==3) { // check if the NACK contains an IP address parameter ppp.pkt.buf[4]=1; // assume the NACK contains our "suggested" IP address sendPppFrame(); // let's request this IP address as ours debugPrintf("Our IPCP ACK (received an IP)\n"); - } // if it's not an IP nack we ignore it + } else { // if it's not an IP nack we ignore it + debugPrintf("IPCP Nack Ignored\n"); + } } /// handle all other IPCP requests (by ignoring them) @@ -475,55 +472,6 @@ } } -/// process an incoming UDP packet -void UDPpacket() -{ - char * udpPkt = ppp.pkt.buf+4; // udp packet start - int headerSizeIP = (( udpPkt[0]&0xf)*4); - char * udpBlock = udpPkt + headerSizeIP; // udp info start - char * udpInf = udpBlock+8; // actual start of info - char * udpSrc = udpBlock; // source port - char * udpDst = udpBlock+2; // destination port - char * udpLen = udpBlock+4; // udp data length - char * udpCks = udpBlock+6; // udp checksum - char * srcIP = udpPkt+12; // udp src addr - char * dstIP = udpPkt+16; // udp dst addr - if (udpLen); // shut up compiler warning for unused udpLen -#ifdef SERIAL_PORT_MONITOR_YES - int srcPort = (udpSrc[0]<<8) | udpSrc[1]; - int dstPort = (udpDst[0]<<8) | udpDst[1]; - int udpLength = ((udpLen[0]<<8) | udpLen[1]) - 8; // size of the actual udp data - if(v0) debugPrintf("UDP %d.%d.%d.%d:%d ", srcIP[0],srcIP[1],srcIP[2],srcIP[3],srcPort); - if(v0) debugPrintf("%d.%d.%d.%d:%d ", dstIP[0],dstIP[1],dstIP[2],dstIP[3],dstPort); - if(v0) debugPrintf("Len %03d", udpLength); - if (v1) { - int printSize = udpLength; - if (printSize > 20) printSize = 20; // print only first 20 characters - for (int i=0; i<printSize; i++) { - char ch = udpInf[i]; - if (ch>31 && ch<127) { - debugPrintf("%c", ch); - } else { - debugPrintf("_"); - } - } - } - if (v0) debugPrintf("\n"); -#endif - if (strncmp(udpInf,"echo", 4)==0) { // if the UDP string starts with "echo" we echo it back - char tempHold[12]; // it's 12 long because we later reuse it when building the TCP pseudo-header - memcpy(tempHold, srcIP,4); - memcpy(srcIP, dstIP,4); - memcpy(dstIP, tempHold,4); // swap ip address source/dest - memcpy(tempHold, udpSrc,2); - memcpy(udpSrc, udpDst,2); - memcpy(udpDst, tempHold,2); // swap udp port source/dest - memcpy(udpInf,"Got:",4); - memset(udpCks,0,2); // we don't compute the checksum (it's optional), so have to zero it - sendPppFrame(); - } -} - /// perform a 16-bit checksum. if the byte count is odd, stuff in an extra zero byte. unsigned int dataCheckSum(unsigned char * ptr, int len) { @@ -550,12 +498,13 @@ } /// perform the checksum on an IP header -void headerCheckSum() +void IpHeaderCheckSum() { - int len =(ppp.pkt.buf[4]&0xf)*4; // length of header in bytes - char * ptr = ppp.pkt.buf+4; // start of ip packet + ppp.pkt.buf[4+10]=0; // zero the checsum in the IP header + ppp.pkt.buf[4+11]=0; // zero the checksum in the IP header + int len =(ppp.pkt.buf[4]&0xf)*4; // length of IP header in bytes + char * ptr = ppp.pkt.buf+4; // start of IP packet int sum=0; - for (int i=0; i<len/2; i++) { int hi = *ptr; ptr++; @@ -567,8 +516,82 @@ } sum = sum + (sum>>16); sum = ~sum; - ppp.pkt.buf[14]= (sum>>8); - ppp.pkt.buf[15]= (sum ); + ppp.pkt.buf[4+10]= (sum>>8); + ppp.pkt.buf[4+11]= (sum ); +} + +/// Process an incoming UDP packet. +/// If the packet starts with the string "echo " or "test" we echo back a special packet +void UDPpacket() +{ + char * ipHeader = ppp.pkt.buf+4; // udp packet start + char * ipSizeBuf = ipHeader+2; // size of IP packet + char * srcIP = ipHeader+12; // IP source + char * dstIP = ipHeader+16; // IP destination + int headerSizeIP = 4*(ipHeader[0]&0xf); // size of IP header + char * udpHeader = ipHeader + headerSizeIP; // udp info start + char * udpSrcPort = udpHeader+0; // source port + char * udpDstPort = udpHeader+2; // destination port + char * udpLen = udpHeader+4; // udp data length + char * udpCheckSum = udpHeader+6; // udp checksum + char * udpData = udpHeader+8; // start of UDP data + int udpLength = ((udpLen[0]<<8) | udpLen[1]); // size of udp packet + int udpDataSize = udpLength - 8; // size of udp data + +#ifdef SERIAL_PORT_MONITOR_YES + int udpSrc = (udpSrcPort[0]<<8)|udpSrcPort[1]; // integer of UDP source port + int udpDst = (udpDstPort[0]<<8)|udpDstPort[1]; // integer of UDP dest port + if(v0) debugPrintf("UDP %d.%d.%d.%d:%d ", srcIP[0],srcIP[1],srcIP[2],srcIP[3],udpSrc); + if(v0) debugPrintf("%d.%d.%d.%d:%d ", dstIP[0],dstIP[1],dstIP[2],dstIP[3],udpDst); + if(v0) debugPrintf("Len %03d", udpLength); + if (v1) { + int printSize = udpLength-8; + if (printSize > 20) printSize = 20; // print only first 20 characters + for (int i=0; i<printSize; i++) { + char ch = udpData[i]; + if (ch>31 && ch<127) { + debugPrintf("%c", ch); + } else { + debugPrintf("_"); + } + } + } + if (v0) debugPrintf("\n"); +#endif + int echoFound = !strncmp(udpData,"echo ",5); // true if UDP message starts with "echo " + int testFound = !strncmp(udpData,"test" ,4); // true if UDP message starts with "test" + if ( (echoFound) || (testFound)) { // if the UDP message starts with "echo " or "test" we answer back + char tempHold[4]; + memcpy(tempHold, srcIP,4); + memcpy(srcIP, dstIP,4); + memcpy(dstIP, tempHold,4); // swap ip address source/dest + memcpy(tempHold, udpSrcPort,2); + memcpy(udpSrcPort, udpDstPort,2); + memcpy(udpDstPort, tempHold,2); // swap udp port source/dest + if (echoFound) { + memcpy(udpData,"Got{",4); // in the UDP data modify "echo" to "Got:" + char endString[] = "} UDP Server: PPP-Blinky\n"; // an appendix + memcpy(udpData+udpLength-8,endString,sizeof(endString)-1); // add endstring size to the UDP message + udpDataSize = udpDataSize + sizeof(endString)-1; // update udp data size with the size of the appendix + } + if (testFound) { + char udpResponse[50]; + int n = 0; + n = n+sprintf(udpResponse+n,"Response count %d\n",ppp.responseCounter++); + memcpy(udpData,udpResponse,n); // copy response to the UDP data area + udpDataSize = n; // new udp data size + } + udpLength = udpDataSize+8; // update udp packet length + int ipSize = headerSizeIP + udpLength; // update ip packet length + ppp.pkt.len = ipSize+2+4; // update ppp packet length + udpLen[0] = udpLength>>8; + udpLen[1] = udpLength; // update UDP length + ipSizeBuf[0] = ipSize>>8; + ipSizeBuf[1] = ipSize; // update IP length + IpHeaderCheckSum(); // update IP header checksum + memset(udpCheckSum,0,2); // we don't yet recompute the checksum (it's optional), so have to zero it + sendPppFrame(); // send the UDP message back + } } /// handle a PING ICMP (internet control message protocol) packet @@ -606,10 +629,8 @@ memcpy(dst, dstAdr,4); memcpy(srcAdr, dst,4); memcpy(dstAdr, src,4); // swap src & dest ip - char * chkSum = ipPkt+10; - chkSum[0]=0; - chkSum[1]=0; - headerCheckSum(); // new ip header checksum +// char * chkSum = ipPkt+10; + IpHeaderCheckSum(); // calculate new ip header checksum #define ICMP_TYPE_ECHO_REPLY 0 icmpType[0]=ICMP_TYPE_ECHO_REPLY; // icmp echo reply icmpSum[0]=0; @@ -816,7 +837,7 @@ int contentLengthStart; // index where HTML starts int httpGet5,httpGet6,httpGetx, httpGetRoot; // temporary storage of strncmp results - ppp.httpPageCount++; // increment the number of frames we have made + ppp.responseCounter++; // increment the number of frames we have made httpGetRoot = strncmp(dataStart, "GET / HTTP/1.", 13); // found a GET to the root directory httpGetx = strncmp(dataStart, "GET /x", 6); // found a GET to /x which we will treat special (anything starting with /x, e.g. /x, /xyz, /xABC?pqr=123 @@ -848,13 +869,13 @@ // change the above to W3C_COMPLIANT_RESPONSE_YES if you want a W3C.org compliant HTTP response #ifdef W3C_COMPLIANT_RESPONSE_YES n=n+sprintf(n+dataStart,"<!DOCTYPE html><title>mbed PPP-Blinky</title>"); // html title (W3C.org required elements) - n=n+sprintf(n+dataStart,"<body>%d</body>",ppp.httpPageCount); // body = the http frame count + n=n+sprintf(n+dataStart,"<body>%d</body>",ppp.responseCounter); // body = the http frame count #else if( httpGet6 == 'b' ) { // if the fetched page is "xb" send a meta command to let the browser continuously reload n=n+sprintf(n+dataStart, "<meta http-equiv=\"refresh\" content=\"0\">"); // reload loop - handy for benchmarking } // /x is a very short page, in fact, it is only a decimal number showing the http Page count - n=n+sprintf(n+dataStart,"%d ",ppp.httpPageCount); // not really valid html but most browsers and curl are ok with it + n=n+sprintf(n+dataStart,"%d ",ppp.responseCounter); // not really valid html but most browsers and curl are ok with it #endif } else { // all other requests get 404 Not Found response with a http frame count - nice for debugging @@ -909,7 +930,7 @@ char * pktLen = ipPkt+2; // 2 bytes char * ident = ipPkt+4; // 2 bytes char * protocol = ipPkt+9; // 1 byte - char * headercheck= ipPkt+10; // 2 bytes +// char * headercheck= ipPkt+10; // 2 bytes char * srcAdr = ipPkt+12; // 4 bytes char * dstAdr = ipPkt+16; // 4 bytes = total of 20 bytes int headerSizeIP = (ihl[0]&0xf)*4; @@ -1012,9 +1033,7 @@ ppp.pkt.len = newPacketSize+4+2; // ip packet length + 4-byte ppp prefix (ff 03 00 21) + 2 fcs (crc) bytes bytes at the end of the packet // the header is all set up, now do the IP and TCP checksums - headercheck[0]=0; // IP header checksum - headercheck[1]=0; // IP header checksum - headerCheckSum(); // calculate the IP header checksum + IpHeaderCheckSum(); // calculate new IP header checksum // 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. @@ -1200,6 +1219,12 @@ } } +/// a sniffer tool to assist in figuring out where in the code we are having characters in the input buffer +void sniff() +{ + if ( pc.readable() ) putsWhileCheckingInput( "Sniff - Char available!\n" ); // if this prints anything it means there is a character in the serial receive buffer +} + /// scan the PPP serial input stream for frame start markers void waitForPppFrame() {