Arianna station communication peripherals.

Dependents:   AutonomousDAQ AutonomousDAQ

SnCommAfarNetIf.cpp

Committer:
uci1
Date:
2018-08-08
Revision:
10:29301aaa8c33
Parent:
4:8328c2972290

File content as of revision 10:29301aaa8c33:

#include "SnCommAfarNetIf.h"

#ifdef ENABLE_AFAR


#include "lwip/inet.h"

//#define DEBUG

SnCommAfarNetIf::SnCommAfarNetIf(const char* rserv,
    const uint16_t rport, const char* ip,
    const char* mask, const char* gate) :
    fUseB64(false),
    fRserv(rserv), fRport(rport),
    fMyIp(ip), fMyMask(mask), fMyGate(gate),
    fEth(0), fSock(0),
    fEthConnected(false), fSockReading(false),
    fEthWriteable(false), fConnAborted(false), fEthSetup(false),
    fRxRd(fRxBuf), fRxWt(fRxBuf), fRxEnd(fRxBuf+RX_BUF_LEN), 
    fRxBufWriteable(true)
    {
    
#ifdef DEBUG
    printf("SnCommAfarNetIf ctor ip=%s, mas=%s, gate=%s\r\n",
        fMyIp.c_str(), fMyMask.c_str(), fMyGate.c_str());
    printf("rserv=%s, rport=%hu\r\n", fRserv.c_str(), fRport);
    printf("calling NewEthAndSocket\r\n");
#endif
    
    NewEthAndSocket();
    
#ifdef DEBUG
    printf("ctor done\r\n");
#endif
}

SnCommAfarNetIf::~SnCommAfarNetIf() {
    delete fEth;
    delete fSock;
}

void SnCommAfarNetIf::Set(const char* remote, const uint16_t rport) {
    fRserv  = remote;
    fRport  = rport;
/*
#ifdef DEBUG
    printf("closing socket\r\n");
#endif
    fSock->close();
*/
#ifdef DEBUG
    printf("disconnect eth\r\n");
#endif
#ifdef DEBUG
    printf("init %s, %s, %s\r\n",fMyIp.c_str(), fMyMask.c_str(), fMyGate.c_str());
#endif
    NewEthAndSocket();
#ifdef DEBUG
    printf("Set done\r\n");
#endif
}

void SnCommAfarNetIf::Set(const char* remote, const uint16_t rport,
                        const char* myip, const char* mask,
                        const char* gate, const bool useb64) {
    fUseB64 = useb64;
    fMyIp   = myip;
    fMyMask = mask;
    fMyGate = gate;
    Set(remote, rport);
}

void SnCommAfarNetIf::NewEthAndSocket() {
#ifdef DEBUG
    printf("deleting fEth(%p)\r\n",(void*)fEth);
#endif
    delete fEth;
    fEthSetup = false;
#ifdef DEBUG
    printf("making ip_addr_t's\r\n");
#endif
    ip_addr_t ip_n, mask_n, gateway_n, dns_n;
    inet_aton(fMyIp.c_str(), &ip_n);
    inet_aton(fMyMask.c_str(), &mask_n);
    inet_aton(fMyGate.c_str(), &gateway_n);
    //inet_aton("0.0.0.0", &dns_n);
    //inet_aton("128.200.1.201", &dns_n);
    inet_aton("157.132.107.58", &dns_n);
#ifdef DEBUG
    printf("new ethernet\r\n");
#endif
    fEth = new EthernetNetIf(
        IpAddr(&ip_n),
        IpAddr(&mask_n),
        IpAddr(&gateway_n),
        IpAddr(&dns_n)
        );
    
    NewSocket();
}

void SnCommAfarNetIf::NewSocket() {
#ifdef DEBUG
    printf("deleting fSock(%p)\r\n",(void*)fSock);
#endif
    delete fSock;

#ifdef DEBUG
    printf("new socket\r\n");
#endif
    fSock = new TCPSocket;

#ifdef DEBUG
    printf("clearing rx buffer\r\n");
#endif
    memset(fRxBuf, 0, RX_BUF_LEN*sizeof(char));
    

#ifdef DEBUG
    printf("setOnEvent\r\n");
#endif
    // catch events
    fSock->setOnEvent(this, &SnCommAfarNetIf::onTCPSocketEvent);

    fEthConnected = false;
    fEthWriteable = false;
}

int32_t SnCommAfarNetIf::PullFromBuffTo(char* const buf, const uint32_t len) {
    // pull 'len' bytes out of the Rx buffer and copy them to buf
    // no check on the length of 'buf' is performed!
    // no check on 'len' is performed!
    
    memcpy(buf, fRxRd, len);
    fRxRd += len;
    if (fRxWt > fRxRd) {
        // there's still data in the buffer
        fRxBufWriteable = false;
        const int32_t nb = fRxWt - fRxRd;
        memmove(fRxBuf, fRxRd, nb); // move it to the beginning (overlap ok in memmove)
        fRxRd  = fRxBuf;
        fRxWt -= nb;
        fRxBufWriteable = true;
    } else {
        // nothing in buffer
        fRxBufWriteable = false;
        fRxRd = fRxWt = fRxBuf;
        fRxBufWriteable = true;
    }
    return len;
}

int32_t SnCommAfarNetIf::ReceiveAll(char* const buf, const uint32_t mlen,
                                    const uint32_t timeout_clock) {
    // TODO: if B64, must return number of bytes of raw (non encoded) message
    //return DoIO(buf, mlen, timeout_clock, &TCPSocketConnection::receive_all);
    // use regular recv; DoIO will do a receive_all but use our timeout
    
    Net::poll();
    // first get out of buffer
    int32_t br = 0;
    while ( (br<mlen) && (fRxRd<fRxWt) ) {
        int32_t bl = fRxWt - fRxRd;
        if (mlen<bl) {
            bl = mlen;
        }
        br += PullFromBuffTo(buf+br, bl);
    }
    // get the rest from the socket
    if (br<mlen) {
        fSockReading = true;
        br += DoIO(buf, mlen, timeout_clock, &TCPSocket::recv, fRxBufWriteable);
        fSockReading = false;
    }
    return br;
}

int32_t SnCommAfarNetIf::SendAll(const char* const data, const uint32_t length,
                                 const uint32_t timeout_clock) {
    // TODO: if B64, must return number of bytes of raw (non encoded) message
    //return DoIO(data, length, timeout_clock, &TCPSocketConnection::send_all);
    // use regular send; DoIO will do a send_all but use our timeout

    Net::poll();
    const char* const buf = data;
#ifdef DEBUG
    const int32_t br = 
#else
    return 
#endif
        DoIO(buf, length, timeout_clock, &TCPSocket::send, fEthWriteable);
#ifdef DEBUG
    printf("SendAll: DoIO returned %d bytes\r\n",br);
    return br;
#endif
}


bool SnCommAfarNetIf::Connect(const uint32_t timeout) {
#ifdef DEBUG
    printf("SnCommAfarNetIf::Connect : setup\r\n");
    printf("fEthConnected=%s\r\n",fEthConnected?"true":"false");
#endif
    if (fEthConnected==false) {
        
#ifdef DEBUG
        printf("fEthSetup=%s\r\n",fEthSetup?"true":"false");
#endif
        if (fEthSetup==false) {
            EthernetErr ethErr = fEth->setup();
        
            while ( (ethErr!=ETH_OK) && (IsTimedOut(timeout)==false) ) {
                wait_ms(250);
                ethErr = fEth->setup();
            }
            
            if (ethErr==ETH_OK) {
                fEthSetup = true;
            }
            
#ifdef DEBUG
            printf("fEthSetup=%s\r\n",fEthSetup?"true":"false");
#endif
            
            // why were these waits here?? -- test in comms lab at McMurdo!
            //wait(10);
            //wait(40); // for use with switch in comms @ McMurdo
        }
        
        if (fEthSetup) {
        
#ifdef DEBUG
            printf("SnCommAfarNetIf::Connect : bind\r\n");
#endif

            ip_addr_t rserv_n;
            inet_aton(fRserv.c_str(), &rserv_n);
            Host server( IpAddr(&rserv_n), fRport );
            //Host server( IpAddr(128,195,204,151), 6655 );
            
#ifdef DEBUG
            printf("SnCommAfarNetIf::Connect : fRserv=%s, fRport=%hu\r\n",
                fRserv.c_str(), fRport);
#endif
            SockConnect(server, timeout);
            /*
            // catch events
            fSock->setOnEvent(this, &SnCommAfarNetIf::onTCPSocketEvent);
            */
#ifdef DEBUG
            printf("SnCommAfarNetIf::Connect : tcp connect\r\n");
#endif
            //fEthConnected = false;
            while ( (fEthConnected==false) && (IsTimedOut(timeout)==false) ) {
                Net::poll();
                if (fConnAborted) {
#ifdef DEBUG
                    printf("SnCommAfarNetIf::Connect : conn aborted. new socket, sockconnect...\r\n");
#endif
                    fConnAborted = false;
                    NewSocket();
                    SockConnect(server, timeout);
                }
            }
            
            fEthWriteable = fEthConnected;
        }
    }

    return fEthConnected;

}

bool SnCommAfarNetIf::SockConnect(const Host& server, const uint32_t timeout) {
#ifdef DEBUG
    printf("SnCommAfarNetIf::SockConnect\r\n");
#endif
    TCPSocketErr bindErr = fSock->connect(server);
    while ( (bindErr!=TCPSOCKET_OK) && (IsTimedOut(timeout)==false) ) {
        wait_ms(250);
        bindErr = fSock->connect(server);
    }
#ifdef DEBUG
    printf("SnCommAfarNetIf::SockConnect: %s\r\n",
        (bindErr==TCPSOCKET_OK) ? "true" : "false");
#endif
    return (bindErr==TCPSOCKET_OK);
}

bool SnCommAfarNetIf::CloseConn(const uint32_t) {
    fEthConnected = false;
    fEthSetup     = false; // new addition -- why was this not here before?
    return (fSock->close() == TCPSOCKET_OK);
}

void SnCommAfarNetIf::onTCPSocketEvent(TCPSocketEvent e)  {
#ifdef DEBUG
    printf("TCPSocketEvent is (%d) ",static_cast<int>(e));
#endif
    if (e == TCPSOCKET_CONNECTED) {
        fEthConnected = true;
#ifdef DEBUG
        printf("TCPSOCKET_CONNECTED\r\n");
#endif
    } else if (e == TCPSOCKET_WRITEABLE) {
#ifdef DEBUG
        printf("TCPSOCKET_WRITEABLE\r\n");
        fEthWriteable=true;
#endif
        //TODO: does this event ever occur?
    } else if (e == TCPSOCKET_READABLE) {
#ifdef DEBUG
        printf("TCPSOCKET_READABLE\r\n");
#endif
        fEthConnected = true;
        // read & buffer the data immediately (if there's room)
        if (fSockReading==false) {
            fSockReading = true;
            fRxWt += DoIO(fRxWt, fRxEnd-fRxWt, time(0)+RX_TIMEOUT, &TCPSocket::recv, fRxBufWriteable);
            fSockReading = false;
#ifdef DEBUG
            printf("fRxBuf now contains:\r\n");
            dispStrBytes(fRxBuf, fRxWt-fRxBuf);
#endif
        }
    } else if (e == TCPSOCKET_CONABRT) {
#ifdef DEBUG
        printf("TCPSOCKET_CONABRT\r\n");
#endif
        fConnAborted = true;
    }
#ifdef DEBUG
      else {
        printf(" %d\r\n",(int)e);
    }
#endif
}


#endif // ENABLE_AFAR