Y SI / Mbed OS TCP-Server-sample

main.cpp

Committer:
YSI
Date:
2021-04-08
Revision:
0:d3cd3a4b962c

File content as of revision 0:d3cd3a4b962c:

#include "main.h"

int main()
{
    Led = eth_status;
    queue = mbed_event_queue();
    while(1) if(eth_connect()) Led = recv();
}

bool eth_connect(void)
{
    switch(eth.get_connection_status())
    {
        case NSAPI_STATUS_DISCONNECTED:
            eth.set_blocking(false);
            eth.set_network(SocketAddress(IP_SERVER), SocketAddress("255.255.255.0"), SocketAddress("192.168.1.1")); // if not static eth.set_dhcp(true);
            eth.attach(callback(&eth_event));
            eth.connect();                              break;
        case NSAPI_STATUS_GLOBAL_UP: return CONNECT;    break;
        default:                                        break;
    }
    return false;
}

void eth_event(nsapi_event_t status, intptr_t param)
{
    switch(param)
    {
        case NSAPI_STATUS_DISCONNECTED: eth_status = RED_DISCONNECTED;  break;
        case NSAPI_STATUS_CONNECTING:if(eth_status == BLUE_CLIENT) clientTCP->close();
                                        eth_status = YELLOW_CONNECTING; break;
        case NSAPI_STATUS_GLOBAL_UP:    eth_status = GREEN_GLOBAL_UP;
                                        if(!CONNECT) serverTCP_connect();
                                        else         serverTCP_event(); break;
        default:                                                        break;
    }
}

void eth_state(void)
{
    switch(eth.get_connection_status())
    {
        case NSAPI_STATUS_DISCONNECTED: eth_status = RED_DISCONNECTED;  break;
        case NSAPI_STATUS_CONNECTING:   eth_status = YELLOW_CONNECTING; break;
        case NSAPI_STATUS_GLOBAL_UP:    eth_status = GREEN_GLOBAL_UP;   break;
        default:                                                        break;
    }
}

bool serverTCP_connect(void)
{
    if(!CONNECT)
        if(serverTCP.open(&eth) == NSAPI_ERROR_OK)
            if(serverTCP.bind(PORT_SERVER) == NSAPI_ERROR_OK)
                if(serverTCP.listen() == NSAPI_ERROR_OK)
                {
                    serverTCP.set_blocking(false);
                    serverTCP.sigio(callback(&serverTCP_event));
                    CONNECT = true;
                }
    return CONNECT;
}

void serverTCP_event(void)
{
    queue->call(&serverTCP_accept);
}

void serverTCP_accept(void)
{
    if(eth_status == GREEN_GLOBAL_UP)
    {
        nsapi_error_t ack = NSAPI_ERROR_WOULD_BLOCK;
        eth_status = MAGENTA_ACCEPT;
        clientTCP = serverTCP.accept(&ack);
        switch(ack)
        {
            case NSAPI_ERROR_OK:
                clientTCP->set_timeout(TIMEOUT_SERVER);   // config client bloquante avec timeout sinon limite de transmission a 1072 octets
                eth_status = BLUE_CLIENT;
            break;
            case NSAPI_ERROR_NO_CONNECTION:
                eth_state();
                serverTCP_event();
            break;
            default:
                eth_state();
            break;
        }
    }
}

enum_status recv(void)
{
    if(eth_connect() && (eth_status == BLUE_CLIENT))
    {
        char buffer[BUFFER_SIZE] = {0};
        nsapi_error_t ack = NSAPI_ERROR_WOULD_BLOCK, size = 0;
        while((ack = clientTCP->recv(&buffer[size], BUFFER_SIZE-size)) > NSAPI_ERROR_OK) size += ack;
        if(!size && (ack == NSAPI_ERROR_OK) || (ack == NSAPI_ERROR_NO_CONNECTION))
        {
            clientTCP->close();
            eth_state();
            serverTCP_event();
        }
        if(size)
        {
            string cmd(buffer);
            for(char &c : cmd) if((c >= 'a') && (c <= 'z')) c += 'A'-'a';
            if(!cmd.empty())
            {
                ostringstream ssend;
                if(cmd.find("GET / HTTP") != string::npos)
                {
                    ssend << "HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=utf-8\r\nAccess-Control-Allow-Origin: *\r\n\r\n";
                    ssend << "<!DOCTYPE html>\r\n<html>\r\n\t<head>\r\n\t\t<title>" << MBED_PROJECT << "</title>\r\n\t\t<meta http-equiv=refresh content=10>\r\n\t</head>";
                    ssend << "\r\n\t<body style=background-color:dimgray>\r\n\t\t<center>\r\n\t\t\t<h1>" << MBED_PROJECT << "</h1>\r\n\t\t</center>\r\n\t</body>\r\n</html>";
                }
                else ssend << "HTTP/1.1 204 No Content\r\n";
                send(ssend.str());
            }
        }
    }
    return eth_status;
}

nsapi_error_t send(const string& buff)
{
    nsapi_error_t ack = NSAPI_ERROR_WOULD_BLOCK;
    string ssend(buff+"\n");
    if((eth_status == BLUE_CLIENT) && !buff.empty())
        ack = clientTCP->send(ssend.c_str(), ssend.size());
    //------------------- HTTP request must close
    clientTCP->close();
    eth_state();
    serverTCP_event();
    //-------------------
    return ack;
}