Machine Vision Status TCP Server

Dependencies:   C12832 EthernetInterface mbed-rtos mbed ConfigFile

TcpDaemon.cpp

Committer:
dwini
Date:
2015-06-15
Revision:
9:60ce5e733ea6
Parent:
8:845dfadaa70d

File content as of revision 9:60ce5e733ea6:

#include "TcpDaemon.h"
#include "Log.h"
#include "StatusIndicator.h"

// Incoming message end
#define END_MSG_SEQUENCE "\r\n"

namespace MachineVision{
    /*
     * TcpDaemon constructor
     *
     * @server_port the port the daemon will be listening on
     */
    TcpDaemon::TcpDaemon(int server_port, PinName accept_led_pin, PinName receive_led_pin, StatusIndicator * indicator)
         : receive_led(receive_led_pin), accept_led(accept_led_pin) {
        this->server_port = server_port;
        this->keepListening = true;
        this->receive_led = 0;
        this->accept_led = 0;
        this->status_indicator = indicator;
    }

    /*
     * Make the daemon start listening for incoming connections
     */
    void TcpDaemon::startListening() {
        if (this->bindSocket()) {
            this->doListen();
        }
    }

    /*
     * Bind to server socket
     *
     * @return true on success
     */
    bool TcpDaemon::bindSocket() {
        if(server.bind(server_port) < 0) {
            Log::e("Bind failed. Error\r\n");
            return false;
        } else {
            Log::d("Bind ok\r\n");
            server.set_blocking(false, TCP_ACCEPT_TIMEOUT);     // Set tot non-blocking
            return true;
        }
    }

    /*
     * Listen for incoming connections
     */
    void TcpDaemon::doListen() {
       
        // Listen for incoming connection
        if (server.listen(MAX_BACKLOG) < 0) {
            Log::w("Listen failed\r\n");
            return;
        }
        
        Log::d("Listening for incoming connection ...\r\n");
        while (this->keepListening) {
            
            // Visual indication
            accept_led = !accept_led;
            
            // Accept connection from an incoming client
            if (server.accept(client) >= 0) {
                Log::d("Client connected: %s\r\n", client.get_address());
                
                // Set non-blocking
                client.set_blocking(false, TCP_TIMEOUT);
                
                while (client.is_connected()) {
                    // Keep receiving messages from the client
                    int read_size = 0;
                    int total_read_size = 0;
                    char * end = NULL;
                    int i_read = 0;
                    
                    int buffer_size = BUFFER_SIZE;
                    char * buffer_offset = buffer;
                    
                    // Read full message from client
                    Log::v("Waiting for message\r\n");
                    do {
                        read_size = client.receive(buffer_offset, buffer_size);
                        receive_led = !receive_led;
                        
                        if (read_size > 0) {
                            total_read_size += read_size;
                            
                            // Null-terminate string
                            buffer[total_read_size] = '\0';
                            Log::v("Received partial: %s\r\n", buffer);
                            
                            // Search for END
                            end = strstr(buffer, END_MSG_SEQUENCE);
                            
                            buffer_size = BUFFER_SIZE-total_read_size;
                            buffer_offset = buffer+total_read_size;
                        } else if (total_read_size > 0) {       // Increment i_read (max timeouts for message)
                            i_read++;
                        }
                    } while (client.is_connected() && total_read_size < BUFFER_SIZE && end == NULL && i_read < MAX_READ_TIMEOUTS);

                    if (end == NULL) {
                        if (total_read_size >= BUFFER_SIZE) {
                            Log::w("Buffer full\r\n");
                        } else if (i_read == MAX_READ_TIMEOUTS) {
                            Log::w("Partial message received. MAX_READ_TIMEOUTS reached.\r\n");
                        }
                        
                    } else {                           
                        // Full string received, lets do our thing
                        Log::v("Received: %s\r\n", buffer);
                        
                        if (strcmp(buffer, STR_OK) == 0) {
                            status_indicator->setStatus(OK);
                        } else if (strcmp(buffer, STR_FAIL) == 0) {
                            status_indicator->setStatus(FAIL);
                        }  else if (strcmp(buffer, STR_CLEAR) == 0) {
                            status_indicator->setStatus(CLEAR);
                        } else {
                            Log::w("Received unknown message: %s\r\n", buffer);
                        }
                    }
                }
                
                Log::d("Client disconnected\r\n");
                fflush(stdout);
                client.close();
            }
        }
    }
}