Lab2_web / Mbed 2 deprecated webserverBlinky

Dependencies:   mbed

Fork of webserverBlinky by RealTimeCompLab2

main.cpp

Committer:
nixnax
Date:
2016-12-29
Revision:
5:27624c02189f
Parent:
4:a469050d5b80
Child:
6:fba4c2e817b8

File content as of revision 5:27624c02189f:

#include "mbed.h"

// Proof-of-concept for TCP/IP using Windows 7/8/10 Dial Up Networking over MBED USB Virtual COM Port

// Toggles LED1 every time the PC sends an IP packet over the PPP link

// Note - turn off all authentication, passwords, compression etc. Simplest link possible.

Serial pc(USBTX, USBRX); // The USB com port - Set this up as a Dial-Up Modem
Serial xx(PC_10, PC_11); // debug port - use a second USB serial port to monitor

DigitalOut led1(LED1);

#define FRAME_7E (0x7e)
#define BUFLEN (1<<14)
char rxbuf[BUFLEN];
char frbuf[3000]; // buffer for ppp frame

struct {
    int online; 
    struct {
        char * buf;
        int head; 
        int tail; 
    } rx; // serial port buffer
    struct {
        int len;
        int crc;
        char * buf;
    } pkt; // ppp buffer
} ppp;

void pppInitStruct(){ ppp.online=0; ppp.rx.buf=rxbuf; ppp.rx.tail=0; ppp.rx.head=0; ppp.pkt.buf=frbuf; ppp.pkt.len=0;}

int crcG; // frame check sequence (CRC) holder
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
void crcReset(){crcG=0xffff;} // crc restart

void rxHandler() // serial port receive interrupt handler
{
    ppp.rx.buf[ppp.rx.head]=pc.getc(); // insert in buffer
    __disable_irq();
    ppp.rx.head=(ppp.rx.head+1)&(BUFLEN-1);
    __enable_irq();
}

int pc_readable() // check if buffer has data
{
    return (ppp.rx.head==ppp.rx.tail) ? 0 : 1 ;
}

int pc_getBuf() // get one character from the buffer
{
    if (pc_readable()) {
        int x = ppp.rx.buf[ ppp.rx.tail ];
        ppp.rx.tail=(ppp.rx.tail+1)&(BUFLEN-1);
        return x;
    }
    return -1;
}


void scanForConnectString(); // scan for connect attempts from pc

int main()
{
    pc.baud(115200);
    xx.baud(115200); 
    xx.puts("\x1b[2J\x1b[H"); // VT100 terminal control code for screen clear/home
    
    pppInitStruct(); // structure containing all the PPP stuff

    pc.attach(&rxHandler,Serial::RxIrq); // activate the receive interrupt handler

    int frameStartIndex, frameEndIndex;
    int frameBusy=0;

    while(1) {
        while ( pc_readable() ) {
            int rx = pc_getBuf();
            if (frameBusy) { 
                if (rx==FRAME_7E) {
                    frameBusy=0; // done gathering frame
                    frameEndIndex=ppp.rx.tail-1; // remember where frame ends
                    void processFrame(int start, int end); // process a received frame
                    processFrame(frameStartIndex, frameEndIndex);
                }
            } 
            else {
                if (rx==FRAME_7E) {
                    frameBusy=1; // start gathering frame
                    frameStartIndex=ppp.rx.tail; // remember where frame starts
                }
            }
        }
        if (ppp.online==0) scanForConnectString(); // try to connect
    }
}

void processFrame(int start, int end) {
    crcReset();
    char * dest = ppp.pkt.buf;
    ppp.pkt.len=0;
    int special=0;
    for (int i=start; i<end; i++) {
        if (special==0) {
            if (rxbuf[i]==0x7d) special=1; 
            else { *dest++ = rxbuf[i]; ppp.pkt.len++; crcDo(rxbuf[i]);}
        } else {
            *dest++ = rxbuf[i]-32; ppp.pkt.len++; crcDo(rxbuf[i]-32);
            special=0;
        }
    }
    ppp.pkt.crc = crcG;
    ppp.rx.head=0; // reuse rxbuf
    ppp.rx.tail=0; // reuse rxbuf
    void determinePacketType(); // declare early
    determinePacketType();
}

void sendFrame(){
    crcReset(); for(int i=0;i<ppp.pkt.len-2;i++) crcDo(ppp.pkt.buf[i]);
    ppp.pkt.buf[ ppp.pkt.len-2 ] = ((~crcG)>>0)&0xff; // update crc lo
    ppp.pkt.buf[ ppp.pkt.len-1 ] = ((~crcG)>>8)&0xff; // update crc hi
    pc.putc(0x7e);
    for(int i=0;i<ppp.pkt.len;i++) {
        unsigned int cc = (unsigned int)ppp.pkt.buf[i];
        if (cc>32) pc.putc(cc);
        else { 
            pc.putc(0x7d); pc.putc(cc+32);
        }
    } 
    pc.putc(0x7e);    
}

void LCPrequestFrame() {
    ppp.pkt.buf[4]=2; // change to an ACK packet
    sendFrame(); // acknowledge their request
    // this is the right time to send our LCP setup request to them
    ppp.pkt.buf[4]=1; // change back to a request
    ppp.pkt.buf[5] =  ppp.pkt.buf[5]+1; // take the next id
    ppp.pkt.buf[16] = ppp.pkt.buf[16] ^ 0x33; // modify magic number
    ppp.pkt.buf[17] = ppp.pkt.buf[16] ^ 0x33; // modify magic number
    sendFrame(); // send our request

}
    
void LCPackFrame() {
    xx.printf("== PPP is up ==\n");
} 

void generalFrame() {
    xx.printf("== General Frame ==\n");
    for(int i=0;i<ppp.pkt.len;i++) xx.printf("%02x ", ppp.pkt.buf[i]);
    xx.printf(" C %02x %02x L=%d\n", ppp.pkt.crc&0xff, (ppp.pkt.crc>>8)&0xff, ppp.pkt.len);
}    

void iPcpFrame() {
    xx.printf("== IPCP Frame ==\n");
    for(int i=0;i<ppp.pkt.len;i++) xx.printf("%02x ", ppp.pkt.buf[i]);
    xx.printf(" C %02x %02x L=%d\n", ppp.pkt.crc&0xff, (ppp.pkt.crc>>8)&0xff, ppp.pkt.len);
    led1 = ppp.pkt.buf[3] & 1; // This is the sequence number so the led blinks on packets
}    

void determinePacketType() {
    char pktLCPReqType  [] = { 0xff, 3, 0xc0, 0x21, 1 }; // LCP requeswt  packet
    char pktLCPAckType  [] = { 0xff, 3, 0xc0, 0x21, 2 }; // LCP ack packet
    char pktIPCPtype    [] = { 0x80, 0x21, 1          }; // ip control packet
    if(0);
    else if (0==memcmp( ppp.pkt.buf,pktLCPReqType,5)) LCPrequestFrame(); 
    else if (0==memcmp( ppp.pkt.buf,pktLCPAckType,5)) LCPackFrame(); 
    else if (0==memcmp( ppp.pkt.buf,pktIPCPtype,3  )) iPcpFrame(); 
    else generalFrame(); // default handler
}    

void scanForConnectString(){
    char * clientFound = strstr( rxbuf, "CLIENTCLIENT" ); // look for PC string
    if( clientFound ) { 
        strcpy( clientFound, "FOUND!FOUND!" ); // overwrite so we don't get fixated
        pc.printf("CLIENTSERVER"); // respond to PC
    }
}