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:
- 85:53e57ff1cf05
- Parent:
- 84:456e73151f11
- Child:
- 87:9f5ac1fabd95
diff -r 456e73151f11 -r 53e57ff1cf05 main.cpp --- a/main.cpp Tue Jul 18 01:01:10 2017 +0000 +++ b/main.cpp Thu Jul 20 01:01:07 2017 +0000 @@ -32,7 +32,20 @@ #define SERIAL_PORT_MONITOR_NO /* or change to SERIAL_PORT_MONITOR_YES */ #ifndef SERIAL_PORT_MONITOR_NO -Serial xx(PC_10, PC_11); // Not required to run, if you get compile error here, change #define SERIAL_PORT_MONITOR_YES to #define SERIAL_PORT_MONITOR_NO + +// here we define the debug serial port for the various target boards +// add yours if it's not in here +#if TARGET_LPC1768 +Serial xx(p9, p10); // Second serial port on LPC1768 - not required to run, if you get compile error here, change #define SERIAL_PORT_MONITOR_YES to #define SERIAL_PORT_MONITOR_NO +#elif TARGET_NUCLEO_F446RE +Serial xx(PC_10, PC_11); // Second serial port on NUCLEO boards - not required to run, if you get compile error here, change #define SERIAL_PORT_MONITOR_YES to #define SERIAL_PORT_MONITOR_NO +#elif TARGET_NUCLEO_L152RE +Serial xx(PC_10, PC_11); // Second serial port on NUCLEO boards - not required to run, if you get compile error here, change #define SERIAL_PORT_MONITOR_YES to #define SERIAL_PORT_MONITOR_NO +#else +#error Add your target board's second serial port here if you want to use debugging - or choose SERIAL_PORT_MONITOR_NO +#endif + + #define debug(x...) xx.printf (x) #else #define debug(x...) {} @@ -91,7 +104,7 @@ int httpFrame; struct { #define RXBUFLEN (1<<14) - char buf[RXBUFLEN]; // RXBUFLEN MUST be a power of two because we use & operator for fast wrap-around in rxHandler + char buf[RXBUFLEN]; // RXBUFLEN MUST be a power of two because we use & operator for fast wrap-around in ring buffer //char * buf; volatile int head; volatile int tail; @@ -118,10 +131,8 @@ { memset( ppp.rx.buf, 0, RXBUFLEN); ppp.online=0; - __disable_irq(); ppp.rx.tail=0; ppp.rx.head=0; - __enable_irq(); ppp.rx.buflevel=0; ppp.pkt.len=0; ppp.ident=1000; @@ -157,13 +168,15 @@ return ppp.crc; } -void rxHandler() // serial port receive interrupt handler + +// fill our own receive buffer with characters from the PPP serial port +void fillbuf() { - while ( pc.readable() ) { - int hd = (ppp.rx.head+1)&(RXBUFLEN-1); // increment/wrap + if ( pc.readable() ) { + int hd = (ppp.rx.head+1)&(RXBUFLEN-1); // increment/wrap head index if ( hd == ppp.rx.tail ) { - debug("Receive buffer is full. ppp.rx.buflevel = %d\n",ppp.rx.buflevel); - break; // watch for buffer full + debug("\nReceive buffer full\n"); + return; } ppp.rx.buf[ppp.rx.head]=pc.getc(); // insert in rx buffer ppp.rx.head = hd; // update head pointer @@ -171,15 +184,13 @@ } } -int rxbufNotEmpty() // check if rx buffer has data +int rxbufNotEmpty() // check if rx buffer has data { - __disable_irq(); // critical section start int emptyStatus = (ppp.rx.head==ppp.rx.tail) ? 0 : 1 ; - __enable_irq(); // critical section end return emptyStatus; } -int pc_getBuf() // get one character from the buffer +int pc_getBuf() // get one character from the buffer { int x = ppp.rx.buf[ ppp.rx.tail ]; ppp.rx.tail=(ppp.rx.tail+1)&(RXBUFLEN-1); @@ -222,7 +233,7 @@ void determinePacketType(); // declaration only determinePacketType(); } else if (v0) { - debug("PPP FCS(crc) Error CRC=%x Length = %d\n",ppp.pkt.crc,ppp.pkt.len); // ignore packets with CRC errors but print a debug line + // debug("PPP FCS(crc) Error CRC=%x Length = %d\n",ppp.pkt.crc,ppp.pkt.len); // ignore packets with CRC errors but print a debug line } } @@ -245,7 +256,7 @@ } } -void sendFrame() // send a PPP frame in HDLC format +void sendFrame() // send a PPP frame in HDLC format { int crc = crcBuf(ppp.pkt.buf, ppp.pkt.len-2); // update crc ppp.pkt.buf[ ppp.pkt.len-2 ] = (~crc>>0); // fcs lo (crc) @@ -491,9 +502,12 @@ char srcIP [16]; snprintf(srcIP,16, "%d.%d.%d.%d", srcAdr[0],srcAdr[1],srcAdr[2],srcAdr[3]); + fillbuf(); char dstIP [16]; snprintf(dstIP,16, "%d.%d.%d.%d", dstAdr[0],dstAdr[1],dstAdr[2],dstAdr[3]); + fillbuf(); if (v0) debug("IP %s %s v%d h%d d%d e%d L%03d ",srcIP,dstIP,versionIP,headerSizeIP,dscpIP,ecnIP,packetLength); + fillbuf(); if (v0) debug("i%04x f%d t%d p%d C%04x\n",identIP,flagsIP,ttlIP,protocolIP,checksumIP); } @@ -536,9 +550,9 @@ int n=0; // number of bytes we have printed so far int nHeader; // byte size of HTTP header int contentLengthStart; // index where HTML starts - + ppp.httpFrame++; // increment count of response frames - + int rootFetch = strncmp(dataStart, "GET / HTTP/1.1", 14); if( rootFetch == 0 ) { @@ -546,7 +560,7 @@ } else { 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 contentLengthStart = n; // remember where Content-Length is in buffer n=n+sprintf(n+dataStart,"?????\r\n"); // leave five spaces for content length - will be updated later @@ -557,12 +571,12 @@ if( rootFetch == 0 ) { // this is where we insert our web page into the buffer n=n+sprintf(n+dataStart,"%s", ourWebPage); - } else { + } 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 } - + 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 @@ -610,8 +624,11 @@ 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]); // use their idea of our seq + 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 #define TCP_FLAG_ACK (1<<4) @@ -629,22 +646,17 @@ // 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; - ack++; case TCP_FLAG_SYN: - // ignore all TCP options by shortening packet to 40 bytes - pktLen[1] = 40; // shorten packet to 40 bytes - packetLength = 40; // shorten packet to 40 bytes - headerSizeTCP = 20; // shorten packet to 40 bytes - tcpSize = 20; // shorten packet to 40 bytes - headerSizeTCP = 20; // shorten packet to 40 bytes - offset[0] = (headerSizeTCP/4)<<4; // shorten packet to 40 bytes - - flagsOut = TCP_FLAG_SYN | TCP_FLAG_ACK; // something wants to connect - ack it - ppp.seq = ppp.seq + 10000; // create a new sequence number (normally random) - seq = ppp.seq; // create a new sequence number (normally random) - ack++; // for SYN flag we have to increase their sequence by 1 + 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 @@ -654,14 +666,14 @@ 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++; + ack_out++; } } break; case TCP_FLAG_FIN: case TCP_FLAG_FIN | TCP_FLAG_ACK: case TCP_FLAG_FIN | TCP_FLAG_ACK | TCP_FLAG_PSH: - ack++; // for FIN flag we have to increase sequence by 1 + ack_out++; // for FIN flag we always have to increase sequence by 1 break; default: return; // ignore remaining packets @@ -684,18 +696,18 @@ memcpy(srctcp, dsttcp,2); memcpy(dsttcp, tempHold,2); // swap ip port source/dest - windowsizetcp[0]=16; // ignore window size negotiation + windowsizetcp[0]=2; // ignore window size negotiation windowsizetcp[1]=0; // ignore winodw size negotiation - acktcp[0]=ack>>24; - acktcp[1]=ack>>16; - acktcp[2]=ack>>8; - acktcp[3]=ack>>0; // save ack 32-bit integer + acktcp[0]=ack_out>>24; + acktcp[1]=ack_out>>16; + acktcp[2]=ack_out>>8; + acktcp[3]=ack_out>>0; // save ack 32-bit integer - seqtcp[0]=seq>>24; - seqtcp[1]=seq>>16; - seqtcp[2]=seq>>8; - seqtcp[3]=seq>>0; // save seq 32-bit integer + seqtcp[0]=seq_out>>24; + seqtcp[1]=seq_out>>16; + seqtcp[2]=seq_out>>8; + seqtcp[3]=seq_out>>0; // save seq 32-bit integer flagbitstcp[1] = flagsOut; // set up the new flags @@ -798,7 +810,7 @@ { debug("LCP Config "); if (ppp.pkt.buf[7] != 4) { - ppp.pkt.buf[4]=4; // allow only no options + ppp.pkt.buf[4]=4; // allow only "no options" which means Maximum Receive Unit (MRU) is 1500 bytes debug("Reject\n"); sendFrame(); } else { @@ -888,7 +900,8 @@ void wait_for_HDLC_frame() { - while(1) + while(1) { + fillbuf(); if ( rxbufNotEmpty() ) { int oldTail = ppp.rx.tail; // remember where the character is located in the buffer int rx = pc_getBuf(); // get the character @@ -905,11 +918,13 @@ } } } + } } void scanForConnectString() { while(ppp.online == 0) { + fillbuf(); // search for Windows Dialup Networking "Direct Connection Between Two Computers" expected connect string char * found1 = strstr( (char *)ppp.rx.buf, "CLIENTCLIENT" ); // also search for HDLC frame start character 0x7e @@ -940,7 +955,6 @@ pppInitStruct(); // initialize all the PPP properties ppp.seq=1000; // initial TCP sequence number - pc.attach(&rxHandler,Serial::RxIrq); // start the receive handler while(1) { scanForConnectString(); // respond to connect command from windows dial up networking while(ppp.online) {