RealtimeCompLab2
Dependencies: mbed
Fork of PPP-Blinky by
main.cpp@9:0992486d4a30, 2016-12-30 (annotated)
- Committer:
- nixnax
- Date:
- Fri Dec 30 13:11:43 2016 +0000
- Revision:
- 9:0992486d4a30
- Parent:
- 8:48e40f1ff316
- Child:
- 10:74f8233f72c0
printing first incoming ip packets
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
nixnax | 0:2cf4880c312a | 1 | #include "mbed.h" |
nixnax | 0:2cf4880c312a | 2 | |
nixnax | 0:2cf4880c312a | 3 | // Proof-of-concept for TCP/IP using Windows 7/8/10 Dial Up Networking over MBED USB Virtual COM Port |
nixnax | 0:2cf4880c312a | 4 | |
nixnax | 4:a469050d5b80 | 5 | // Toggles LED1 every time the PC sends an IP packet over the PPP link |
nixnax | 4:a469050d5b80 | 6 | |
nixnax | 4:a469050d5b80 | 7 | // Note - turn off all authentication, passwords, compression etc. Simplest link possible. |
nixnax | 0:2cf4880c312a | 8 | |
nixnax | 9:0992486d4a30 | 9 | // Handy links |
nixnax | 6:fba4c2e817b8 | 10 | // http://atari.kensclassics.org/wcomlog.htm |
nixnax | 6:fba4c2e817b8 | 11 | // https://technet.microsoft.com/en-us/library/cc957992.aspx |
nixnax | 6:fba4c2e817b8 | 12 | // http://www.sunshine2k.de/coding/javascript/crc/crc_js.html |
nixnax | 9:0992486d4a30 | 13 | // https://en.wikibooks.org/wiki/Serial_Programming/IP_Over_Serial_Connections |
nixnax | 6:fba4c2e817b8 | 14 | |
nixnax | 6:fba4c2e817b8 | 15 | Serial pc(USBTX, USBRX); // The USB com port - Set this up as a Dial-Up Modem on your pc |
nixnax | 4:a469050d5b80 | 16 | Serial xx(PC_10, PC_11); // debug port - use a second USB serial port to monitor |
nixnax | 0:2cf4880c312a | 17 | |
nixnax | 9:0992486d4a30 | 18 | #define debug(x) xx.printf( x ) |
nixnax | 9:0992486d4a30 | 19 | |
nixnax | 4:a469050d5b80 | 20 | DigitalOut led1(LED1); |
nixnax | 4:a469050d5b80 | 21 | |
nixnax | 4:a469050d5b80 | 22 | #define FRAME_7E (0x7e) |
nixnax | 9:0992486d4a30 | 23 | #define BUFLEN (1<<12) |
nixnax | 4:a469050d5b80 | 24 | char rxbuf[BUFLEN]; |
nixnax | 4:a469050d5b80 | 25 | char frbuf[3000]; // buffer for ppp frame |
nixnax | 0:2cf4880c312a | 26 | |
nixnax | 4:a469050d5b80 | 27 | struct { |
nixnax | 4:a469050d5b80 | 28 | int online; |
nixnax | 4:a469050d5b80 | 29 | struct { |
nixnax | 4:a469050d5b80 | 30 | char * buf; |
nixnax | 4:a469050d5b80 | 31 | int head; |
nixnax | 4:a469050d5b80 | 32 | int tail; |
nixnax | 9:0992486d4a30 | 33 | int total; |
nixnax | 4:a469050d5b80 | 34 | } rx; // serial port buffer |
nixnax | 4:a469050d5b80 | 35 | struct { |
nixnax | 6:fba4c2e817b8 | 36 | int id; |
nixnax | 4:a469050d5b80 | 37 | int len; |
nixnax | 4:a469050d5b80 | 38 | int crc; |
nixnax | 4:a469050d5b80 | 39 | char * buf; |
nixnax | 4:a469050d5b80 | 40 | } pkt; // ppp buffer |
nixnax | 4:a469050d5b80 | 41 | } ppp; |
nixnax | 0:2cf4880c312a | 42 | |
nixnax | 9:0992486d4a30 | 43 | void pppInitStruct(){ ppp.online=0; ppp.rx.buf=rxbuf; ppp.rx.tail=0; ppp.rx.head=0; ppp.rx.total=0; ppp.pkt.buf=frbuf; ppp.pkt.len=0;} |
nixnax | 4:a469050d5b80 | 44 | |
nixnax | 4:a469050d5b80 | 45 | int crcG; // frame check sequence (CRC) holder |
nixnax | 4:a469050d5b80 | 46 | void crcDo(int x){for (int i=0;i<8;i++){crcG=((crcG&1)^(x&1))?(crcG>>1)^0x8408:crcG>>1;x>>=1;}} // crc calculator |
nixnax | 4:a469050d5b80 | 47 | void crcReset(){crcG=0xffff;} // crc restart |
nixnax | 9:0992486d4a30 | 48 | int crcBuf(char * buf, int size){crcReset();for(int i=0;i<size;i++)crcDo(*buf++);return crcG;} // crc on a block of memory |
nixnax | 0:2cf4880c312a | 49 | |
nixnax | 0:2cf4880c312a | 50 | void rxHandler() // serial port receive interrupt handler |
nixnax | 0:2cf4880c312a | 51 | { |
nixnax | 4:a469050d5b80 | 52 | ppp.rx.buf[ppp.rx.head]=pc.getc(); // insert in buffer |
nixnax | 0:2cf4880c312a | 53 | __disable_irq(); |
nixnax | 4:a469050d5b80 | 54 | ppp.rx.head=(ppp.rx.head+1)&(BUFLEN-1); |
nixnax | 9:0992486d4a30 | 55 | ppp.rx.total++; |
nixnax | 0:2cf4880c312a | 56 | __enable_irq(); |
nixnax | 0:2cf4880c312a | 57 | } |
nixnax | 0:2cf4880c312a | 58 | |
nixnax | 0:2cf4880c312a | 59 | int pc_readable() // check if buffer has data |
nixnax | 0:2cf4880c312a | 60 | { |
nixnax | 4:a469050d5b80 | 61 | return (ppp.rx.head==ppp.rx.tail) ? 0 : 1 ; |
nixnax | 0:2cf4880c312a | 62 | } |
nixnax | 0:2cf4880c312a | 63 | |
nixnax | 0:2cf4880c312a | 64 | int pc_getBuf() // get one character from the buffer |
nixnax | 0:2cf4880c312a | 65 | { |
nixnax | 0:2cf4880c312a | 66 | if (pc_readable()) { |
nixnax | 4:a469050d5b80 | 67 | int x = ppp.rx.buf[ ppp.rx.tail ]; |
nixnax | 4:a469050d5b80 | 68 | ppp.rx.tail=(ppp.rx.tail+1)&(BUFLEN-1); |
nixnax | 0:2cf4880c312a | 69 | return x; |
nixnax | 0:2cf4880c312a | 70 | } |
nixnax | 0:2cf4880c312a | 71 | return -1; |
nixnax | 0:2cf4880c312a | 72 | } |
nixnax | 0:2cf4880c312a | 73 | |
nixnax | 4:a469050d5b80 | 74 | void scanForConnectString(); // scan for connect attempts from pc |
nixnax | 1:9e03798d4367 | 75 | |
nixnax | 9:0992486d4a30 | 76 | void processFrame(int start, int end) { // process received frame |
nixnax | 9:0992486d4a30 | 77 | if(start==end) { xx.printf("Null Frame c=%d\n",ppp.rx.total); pc.putc(0x7e); return; } |
nixnax | 9:0992486d4a30 | 78 | crcReset(); |
nixnax | 9:0992486d4a30 | 79 | char * dest = ppp.pkt.buf; |
nixnax | 9:0992486d4a30 | 80 | ppp.pkt.len=0; |
nixnax | 9:0992486d4a30 | 81 | int unstuff=0; |
nixnax | 9:0992486d4a30 | 82 | for (int i=start; i<end; i++) { |
nixnax | 9:0992486d4a30 | 83 | if (unstuff==0) { |
nixnax | 9:0992486d4a30 | 84 | if (rxbuf[i]==0x7d) unstuff=1; |
nixnax | 9:0992486d4a30 | 85 | else { *dest++ = rxbuf[i]; ppp.pkt.len++; crcDo(rxbuf[i]);} |
nixnax | 9:0992486d4a30 | 86 | } else { |
nixnax | 9:0992486d4a30 | 87 | *dest++ = rxbuf[i]^0x20; ppp.pkt.len++; crcDo((int)rxbuf[i]^0x20); |
nixnax | 9:0992486d4a30 | 88 | unstuff=0; |
nixnax | 9:0992486d4a30 | 89 | } |
nixnax | 9:0992486d4a30 | 90 | } |
nixnax | 9:0992486d4a30 | 91 | ppp.pkt.crc = crcG & 0xffff; |
nixnax | 9:0992486d4a30 | 92 | if (ppp.pkt.crc == 0xf0b8) { // check for good CRC |
nixnax | 9:0992486d4a30 | 93 | void determinePacketType(); // declare early |
nixnax | 9:0992486d4a30 | 94 | determinePacketType(); |
nixnax | 9:0992486d4a30 | 95 | } else { |
nixnax | 9:0992486d4a30 | 96 | xx.printf("CRC was %x \n",ppp.pkt.crc); |
nixnax | 9:0992486d4a30 | 97 | for(int i=0;i<ppp.pkt.len;i++)xx.printf("%02x ", ppp.pkt.buf[i]); |
nixnax | 9:0992486d4a30 | 98 | xx.printf("\nLen = %d\n", ppp.pkt.len); |
nixnax | 9:0992486d4a30 | 99 | } |
nixnax | 9:0992486d4a30 | 100 | } |
nixnax | 9:0992486d4a30 | 101 | |
nixnax | 9:0992486d4a30 | 102 | |
nixnax | 9:0992486d4a30 | 103 | void generalFrame() { |
nixnax | 9:0992486d4a30 | 104 | debug("== General Frame ==\n"); |
nixnax | 9:0992486d4a30 | 105 | for(int i=0;i<ppp.pkt.len;i++) xx.printf("%02x ", ppp.pkt.buf[i]); |
nixnax | 9:0992486d4a30 | 106 | xx.printf(" C %02x %02x L=%d\n", ppp.pkt.crc&0xff, (ppp.pkt.crc>>8)&0xff, ppp.pkt.len); |
nixnax | 9:0992486d4a30 | 107 | } |
nixnax | 9:0992486d4a30 | 108 | |
nixnax | 9:0992486d4a30 | 109 | void sendFrame(){ |
nixnax | 9:0992486d4a30 | 110 | int crc = crcBuf(ppp.pkt.buf, ppp.pkt.len-2); // get crc |
nixnax | 9:0992486d4a30 | 111 | ppp.pkt.buf[ ppp.pkt.len-2 ] = (~crc>>0); // fcs lo |
nixnax | 9:0992486d4a30 | 112 | ppp.pkt.buf[ ppp.pkt.len-1 ] = (~crc>>8); // fcs hi |
nixnax | 9:0992486d4a30 | 113 | pc.putc(0x7e); // frame flag |
nixnax | 9:0992486d4a30 | 114 | for(int i=0;i<ppp.pkt.len;i++) { |
nixnax | 9:0992486d4a30 | 115 | unsigned int cc = (unsigned int)ppp.pkt.buf[i]; |
nixnax | 9:0992486d4a30 | 116 | if (cc>32) pc.putc(cc); else {pc.putc(0x7d); pc.putc(cc+32);} |
nixnax | 9:0992486d4a30 | 117 | } |
nixnax | 9:0992486d4a30 | 118 | pc.putc(0x7e); // frame flag |
nixnax | 9:0992486d4a30 | 119 | } |
nixnax | 9:0992486d4a30 | 120 | |
nixnax | 9:0992486d4a30 | 121 | void ipRequestHandler(){ |
nixnax | 9:0992486d4a30 | 122 | debug("IPCP Conf "); |
nixnax | 9:0992486d4a30 | 123 | if ( ppp.pkt.buf[7] != 4 ) { |
nixnax | 9:0992486d4a30 | 124 | debug("Rej\n"); // reject if any options are requested |
nixnax | 9:0992486d4a30 | 125 | ppp.pkt.buf[4]=4; |
nixnax | 9:0992486d4a30 | 126 | sendFrame(); |
nixnax | 9:0992486d4a30 | 127 | } else { |
nixnax | 9:0992486d4a30 | 128 | debug("Ack\n"); |
nixnax | 9:0992486d4a30 | 129 | ppp.pkt.buf[4]=2; // ack the minimum |
nixnax | 9:0992486d4a30 | 130 | sendFrame(); // acknowledge |
nixnax | 9:0992486d4a30 | 131 | // send our own request now |
nixnax | 9:0992486d4a30 | 132 | debug("IPCP Ask\n"); |
nixnax | 9:0992486d4a30 | 133 | ppp.pkt.buf[4]=1; // request the minimum |
nixnax | 9:0992486d4a30 | 134 | ppp.pkt.buf[5]++; // next sequence |
nixnax | 9:0992486d4a30 | 135 | sendFrame(); // this is our request |
nixnax | 9:0992486d4a30 | 136 | } |
nixnax | 9:0992486d4a30 | 137 | } |
nixnax | 9:0992486d4a30 | 138 | |
nixnax | 9:0992486d4a30 | 139 | void ipAckHandler(){ debug("IPCP Grant\n"); } |
nixnax | 9:0992486d4a30 | 140 | |
nixnax | 9:0992486d4a30 | 141 | void ipNackHandler(){ debug("IPCP Nack\n"); } |
nixnax | 9:0992486d4a30 | 142 | |
nixnax | 9:0992486d4a30 | 143 | void ipDefaultHandler(){ debug("IPCP Other\n"); } |
nixnax | 9:0992486d4a30 | 144 | |
nixnax | 9:0992486d4a30 | 145 | void IPCPframe() { |
nixnax | 9:0992486d4a30 | 146 | led1 = ppp.pkt.buf[5] & 1; // This is the sequence number so the led blinks on packets |
nixnax | 9:0992486d4a30 | 147 | //ppp.pkt.id = ppp.pkt.buf[5]; // remember the sequence number |
nixnax | 9:0992486d4a30 | 148 | int code = ppp.pkt.buf[4]; // packet type is here |
nixnax | 9:0992486d4a30 | 149 | switch (code) { |
nixnax | 9:0992486d4a30 | 150 | case 1: ipRequestHandler(); break; |
nixnax | 9:0992486d4a30 | 151 | case 2: ipAckHandler(); break; |
nixnax | 9:0992486d4a30 | 152 | case 3: ipNackHandler(); break; |
nixnax | 9:0992486d4a30 | 153 | default: ipDefaultHandler(); |
nixnax | 9:0992486d4a30 | 154 | } |
nixnax | 9:0992486d4a30 | 155 | } |
nixnax | 9:0992486d4a30 | 156 | |
nixnax | 9:0992486d4a30 | 157 | void IPframe() { |
nixnax | 9:0992486d4a30 | 158 | xx.printf("IP frame proto %3d len %4d %d.%d.%d.%d %d.%d.%d.%d\n", ppp.pkt.buf[13],(ppp.pkt.buf[6]<<8)+ppp.pkt.buf[7],ppp.pkt.buf[16],ppp.pkt.buf[17],ppp.pkt.buf[18],ppp.pkt.buf[19],ppp.pkt.buf[20],ppp.pkt.buf[21],ppp.pkt.buf[22],ppp.pkt.buf[23] ); |
nixnax | 9:0992486d4a30 | 159 | } |
nixnax | 9:0992486d4a30 | 160 | |
nixnax | 9:0992486d4a30 | 161 | |
nixnax | 9:0992486d4a30 | 162 | |
nixnax | 9:0992486d4a30 | 163 | void LCPconfReq() { |
nixnax | 9:0992486d4a30 | 164 | debug("LCP Conf "); |
nixnax | 9:0992486d4a30 | 165 | if (ppp.pkt.buf[7] != 4) { |
nixnax | 9:0992486d4a30 | 166 | ppp.pkt.buf[4]=4; // allow only minimal requests |
nixnax | 9:0992486d4a30 | 167 | debug("Rej\n"); |
nixnax | 9:0992486d4a30 | 168 | sendFrame(); |
nixnax | 9:0992486d4a30 | 169 | } else { |
nixnax | 9:0992486d4a30 | 170 | ppp.pkt.buf[4]=2; // ack zero conf |
nixnax | 9:0992486d4a30 | 171 | debug("Ack\n"); |
nixnax | 9:0992486d4a30 | 172 | sendFrame(); |
nixnax | 9:0992486d4a30 | 173 | debug("LCP ask\n"); |
nixnax | 9:0992486d4a30 | 174 | ppp.pkt.buf[4]=1; // request zero conf |
nixnax | 9:0992486d4a30 | 175 | sendFrame(); |
nixnax | 9:0992486d4a30 | 176 | } |
nixnax | 9:0992486d4a30 | 177 | } |
nixnax | 9:0992486d4a30 | 178 | |
nixnax | 9:0992486d4a30 | 179 | void LCPconfAck() { |
nixnax | 9:0992486d4a30 | 180 | debug("LCP Ack\n"); |
nixnax | 9:0992486d4a30 | 181 | } |
nixnax | 9:0992486d4a30 | 182 | |
nixnax | 9:0992486d4a30 | 183 | void LCPend(){ |
nixnax | 9:0992486d4a30 | 184 | debug("LCP End\n"); |
nixnax | 9:0992486d4a30 | 185 | ppp.online=0; |
nixnax | 9:0992486d4a30 | 186 | ppp.pkt.buf[4]=6; |
nixnax | 9:0992486d4a30 | 187 | sendFrame(); |
nixnax | 9:0992486d4a30 | 188 | } |
nixnax | 9:0992486d4a30 | 189 | |
nixnax | 9:0992486d4a30 | 190 | void LCPother(){ |
nixnax | 9:0992486d4a30 | 191 | debug("LCP Other\n"); |
nixnax | 9:0992486d4a30 | 192 | generalFrame(); |
nixnax | 9:0992486d4a30 | 193 | } |
nixnax | 9:0992486d4a30 | 194 | |
nixnax | 9:0992486d4a30 | 195 | void LCPframe(){ |
nixnax | 9:0992486d4a30 | 196 | int code = ppp.pkt.buf[4]; |
nixnax | 9:0992486d4a30 | 197 | switch (code) { |
nixnax | 9:0992486d4a30 | 198 | case 1: LCPconfReq(); break; |
nixnax | 9:0992486d4a30 | 199 | case 2: LCPconfAck(); break; |
nixnax | 9:0992486d4a30 | 200 | case 5: LCPend(); break; |
nixnax | 9:0992486d4a30 | 201 | default: LCPother(); |
nixnax | 9:0992486d4a30 | 202 | } |
nixnax | 9:0992486d4a30 | 203 | } |
nixnax | 9:0992486d4a30 | 204 | |
nixnax | 9:0992486d4a30 | 205 | void xx21frame() { |
nixnax | 9:0992486d4a30 | 206 | debug("Unknown frame type ff 03 xx 21\n"); |
nixnax | 9:0992486d4a30 | 207 | } |
nixnax | 9:0992486d4a30 | 208 | |
nixnax | 9:0992486d4a30 | 209 | void determinePacketType() { |
nixnax | 9:0992486d4a30 | 210 | if ( ppp.pkt.buf[0] != 0xff ) {debug("byte0 != ff\n"); return;} |
nixnax | 9:0992486d4a30 | 211 | if ( ppp.pkt.buf[1] != 3 ) {debug("byte1 != 3\n"); return;} |
nixnax | 9:0992486d4a30 | 212 | if ( ppp.pkt.buf[3] != 0x21 ) {debug("byte2 != 21\n"); return;} |
nixnax | 9:0992486d4a30 | 213 | int packetType = ppp.pkt.buf[2]; |
nixnax | 9:0992486d4a30 | 214 | switch (packetType) { |
nixnax | 9:0992486d4a30 | 215 | case 0xc0: LCPframe(); break; |
nixnax | 9:0992486d4a30 | 216 | case 0x80: IPCPframe(); break; |
nixnax | 9:0992486d4a30 | 217 | case 0x00: IPframe(); break; |
nixnax | 9:0992486d4a30 | 218 | default: xx21frame(); break; |
nixnax | 9:0992486d4a30 | 219 | } |
nixnax | 9:0992486d4a30 | 220 | } |
nixnax | 9:0992486d4a30 | 221 | |
nixnax | 9:0992486d4a30 | 222 | void scanForConnectString() { |
nixnax | 9:0992486d4a30 | 223 | if ( ppp.online==0 ) { |
nixnax | 9:0992486d4a30 | 224 | char * clientFound = strstr( rxbuf, "CLIENTCLIENT" ); // look for PC string |
nixnax | 9:0992486d4a30 | 225 | if( clientFound ) { |
nixnax | 9:0992486d4a30 | 226 | strcpy( clientFound, "FOUND!FOUND!" ); // overwrite so we don't get fixated |
nixnax | 9:0992486d4a30 | 227 | pc.printf("CLIENTSERVER"); // respond to PC |
nixnax | 9:0992486d4a30 | 228 | ppp.online=1; // we can stop looking for the string |
nixnax | 9:0992486d4a30 | 229 | debug("Connect string found\n"); |
nixnax | 9:0992486d4a30 | 230 | } |
nixnax | 9:0992486d4a30 | 231 | } |
nixnax | 9:0992486d4a30 | 232 | } |
nixnax | 9:0992486d4a30 | 233 | |
nixnax | 0:2cf4880c312a | 234 | int main() |
nixnax | 0:2cf4880c312a | 235 | { |
nixnax | 9:0992486d4a30 | 236 | pc.baud(9600); |
nixnax | 4:a469050d5b80 | 237 | xx.baud(115200); |
nixnax | 9:0992486d4a30 | 238 | xx.puts("\x1b[2J\x1b[HReady\n"); // VT100 code for clear screen & home |
nixnax | 4:a469050d5b80 | 239 | |
nixnax | 9:0992486d4a30 | 240 | pppInitStruct(); // initialize all the PPP properties |
nixnax | 4:a469050d5b80 | 241 | |
nixnax | 9:0992486d4a30 | 242 | pc.attach(&rxHandler,Serial::RxIrq); // start the receive handler |
nixnax | 4:a469050d5b80 | 243 | |
nixnax | 9:0992486d4a30 | 244 | int frameStartIndex, frameEndIndex; int frameBusy=0; |
nixnax | 4:a469050d5b80 | 245 | |
nixnax | 0:2cf4880c312a | 246 | while(1) { |
nixnax | 9:0992486d4a30 | 247 | if ( ppp.online==0 ) scanForConnectString(); // try to connect |
nixnax | 0:2cf4880c312a | 248 | while ( pc_readable() ) { |
nixnax | 1:9e03798d4367 | 249 | int rx = pc_getBuf(); |
nixnax | 9:0992486d4a30 | 250 | wait(0.001); |
nixnax | 4:a469050d5b80 | 251 | if (frameBusy) { |
nixnax | 4:a469050d5b80 | 252 | if (rx==FRAME_7E) { |
nixnax | 4:a469050d5b80 | 253 | frameBusy=0; // done gathering frame |
nixnax | 4:a469050d5b80 | 254 | frameEndIndex=ppp.rx.tail-1; // remember where frame ends |
nixnax | 4:a469050d5b80 | 255 | void processFrame(int start, int end); // process a received frame |
nixnax | 4:a469050d5b80 | 256 | processFrame(frameStartIndex, frameEndIndex); |
nixnax | 4:a469050d5b80 | 257 | } |
nixnax | 4:a469050d5b80 | 258 | } |
nixnax | 4:a469050d5b80 | 259 | else { |
nixnax | 4:a469050d5b80 | 260 | if (rx==FRAME_7E) { |
nixnax | 4:a469050d5b80 | 261 | frameBusy=1; // start gathering frame |
nixnax | 9:0992486d4a30 | 262 | frameStartIndex=ppp.rx.tail; // remember where frame started |
nixnax | 4:a469050d5b80 | 263 | } |
nixnax | 0:2cf4880c312a | 264 | } |
nixnax | 4:a469050d5b80 | 265 | } |
nixnax | 7:ab147f5e97ac | 266 | } |
nixnax | 7:ab147f5e97ac | 267 | } |