program to test the sending of small packets of data from memory over EthernetInterface using mbed rtos

Dependencies:   EthernetInterface mbed-rtos mbed

Fork of testEthIntfTCPSocket by S K UCI

main.cpp

Committer:
uci1
Date:
2013-09-27
Revision:
2:a625f2ff0174
Parent:
1:6b90cbfe0c9e

File content as of revision 2:a625f2ff0174:

#include "mbed.h"

#include "TCPSocketConnection.h"
#include "EthernetInterface.h"
#include "string"
#include "fakeData.h"

//#define DEBUG                 // turn on debug output if defined (note this slows down processing due to serial baud rate!)
//#define PRINT_DOIO_RESULT     // print the number of bytes DoIO returns

DigitalOut led1(LED1);
DigitalOut led2(LED2);
DigitalOut led3(LED3);
DigitalOut led4(LED4);

static const char*          kRserv      = "128.195.204.151";
static const unsigned short kRport      = 6666;

static const char*          kMyIp       = "128.195.204.148";
static const char*          kMyMask     = "255.255.255.0";
static const char*          kMyGate     = "128.195.204.1";

static const unsigned int   kBSTime     = 946684800u; // 1/1/2000 00:00:00 UTC
static const int            kSecsPerDay = 3600*24;
static const int            kBuffSize   = 1024;
// all chunks must be smaller than kBuffSize
static const int            kNCsizes    = 5;
static const int            gChunkSize[kNCsizes] = { 9, 26, 711, 40, 432 };
static const int            kTotFakeDat = 2097152; // if sending fake data, send 2 MB total
static const int            kTimeout    = 300; // seconds

static char                 gBuff[kBuffSize];
static LocalFileSystem      local("local");
static EthernetInterface*   gEth(0);
static TCPSocketConnection* gSock(0);
static Serial               gCpu( USBTX, USBRX );

// function pointer to send, receive, etc
typedef int (TCPSocketConnection::*TCPSendRecv)(char*, int);
#define CALL_MEMBER_FN(object,ptrToMember)  ((object).*(ptrToMember))

// forward declarations
bool Connect(const int timeout);
void SendData(FILE* inf, const int timeout);
FILE* OpenSDFile(const char* name, const char* mode);
void SendAllFakeData(const int totalBytes, const int timeout);
void SendAllFiles(const int timeout);
bool IsTimedOut(const int timeout_clock);
void dispStrBytes(const char* const s, const int len);
int DoIO(char* const data,
         const int length,
         const int timeout_clock,
         TCPSendRecv fcn);
int ReceiveAll(char* const buf, const int mlen, const int timeout_clock);
int SendAll(char* const data, const int length, const int timeout_clock);


int main() {
    led1=1;
    set_time(kBSTime);
    if (Connect(time(0)+kTimeout)) {
        led2=1;
        SendAllFakeData(kTotFakeDat, time(0)+kTimeout);
    } else {
        led4=1;
    }
    if (gSock!=0) {
        gSock->close();
    }
    if (gEth!=0) {
        gEth->disconnect();
    }
    while (true) {
        led1=0; Thread::wait(500); led1=1; Thread::wait(500);
    }
}

bool Connect(const int timeout) {

#ifdef DEBUG
    printf("Connect\r\n");
#endif
    
    gEth = new EthernetInterface;
    gSock = new TCPSocketConnection;

#ifdef DEBUG
    printf("made eth and sock\r\n");
#endif

    gEth->init(kMyIp, kMyMask, kMyGate);

#ifdef DEBUG
    printf("called init\r\n");
#endif

    bool isConn = false;

    while ( (isConn==false) && (IsTimedOut(timeout)==false) ) {
        Thread::wait(250); // TODO : change wait!!
        isConn = (gEth->connect()==0);
    }
#ifdef DEBUG
    printf("eth isConn=%d\r\n",(int)isConn);
#endif
    
    isConn=false;
    while ( (isConn==false) && (IsTimedOut(timeout)==false) ) {
        Thread::wait(250);
        isConn = (gSock->connect(kRserv, kRport)==0);
    }
#ifdef DEBUG
    printf("sock isConn=%d\r\n",(int)isConn);
#endif
    return isConn;
}

void SendAllFakeData(const int totalBytes, const int timeout) {
    // send the fake data in chunks

    const int* const csend = gChunkSize + kNCsizes;
    const int* cs = gChunkSize;
    
    int br=0;  // bytes read/sent so far
    int tcs=0; // this chunk size
    while ( br<totalBytes ) {
        
        // read a chunk
        tcs = (*cs < kFakeDataSize) ? (*cs) : kFakeDataSize;
        memcpy(gBuff, gFakeData, tcs);
        
        // send this chunk
        br += SendAll(gBuff, tcs, timeout);
        
        // change chunk size
        ++cs;
        if (cs==csend) {
            cs = gChunkSize;
        }
    }
}

bool IsTimedOut(const int timeout_clock) {
    if (timeout_clock==0) {
        // for not obeying timeout option
        return false;
    } else {
        const int ct = time(0);
        if ( (ct==0) ||
             (abs(static_cast<double>(timeout_clock-ct))>kSecsPerDay) ) {
            // clock problems! timeout now.
#ifdef DEBUG
            printf("clock problem. timing out\r\n");
#endif            
            return true;
        } else {
            const bool rt = (ct>timeout_clock);
#ifdef DEBUG
            if (rt) {
                printf("timing out.\r\n");
            }
#endif
            return rt;
        }
    }
}

void dispStrBytes(const char* const s, const int len) {
    const char* c = s;
    for (int i=0; i<len; ++i, ++c) {
        if (*c>0x1F && *c<0x7F) {
            printf("%c", *c);
        } else {
            printf(".x%02x.", *c);
        }
    }
}

int DoIO(char* const data,
         const int length,
         const int timeout_clock,
         TCPSendRecv fcn) {
    // TODO: if B64, must return number of bytes of raw (non encoded) message
#ifdef DEBUG
    printf("DoIO data:\r\n");
    dispStrBytes(data, length);
    printf("\r\n");
#endif
    int res=0;
    int b=0;
    while ( (length>b) ) {
        if (IsTimedOut(timeout_clock)) {
#ifdef DEBUG
            printf("DoIO timing out\r\n");
#endif
            break;
        }
        res = CALL_MEMBER_FN(*gSock, fcn)(data+b, length-b);
        switch (res) {
            case -1:
                // TODO: how to check the error?
                continue;
            case 0:
                return b;
            default:
                b += res;
        };
        //wait_ms(100);
    }
#if defined(DEBUG) || defined(PRINT_DOIO_RESULT)
    printf("return b=%d\r\n",b);
#endif
    return b; // timeout
}

int ReceiveAll(char* const buf, const int mlen, const int timeout_clock) {
    // use regular receive; DoIO will do a receive_all but use our timeout
    return DoIO(buf, mlen, timeout_clock, &TCPSocketConnection::receive);
}

int SendAll(char* const data, const int length, const int timeout_clock) {
    // use regular send; DoIO will do a send_all but use our timeout
    return DoIO(data, length, timeout_clock, &TCPSocketConnection::send);
}