1.1.27.27.3 Example - UDP Client

#include <string.h>

#include "winc_socket.h"

typedef enum
{
    MODULE_STATE_INIT,
    MODULE_STATE_SOCKET_WAITING,
    MODULE_STATE_CONNECTING,
    MODULE_STATE_CONNECTED,
    MODULE_STATE_DISCONNECTED,
    MODULE_STATE_ERROR,
} MODULE_STATE;

typedef struct
{
    union sockaddr_union sockAddr;
} BSOCK_UDP_CLIENT_INIT_TYPE;

static MODULE_STATE                 state;
static int                          sockh;
static BSOCK_UDP_CLIENT_INIT_TYPE   initData = {0};

void bsock_udp_client_init(void *pInitData)
{
    if (NULL != pInitData)
    {
        memcpy(&initData, pInitData, sizeof(BSOCK_UDP_CLIENT_INIT_TYPE));
    }

    state = MODULE_STATE_INIT;
}

void bsock_udp_client_run(void)
{
    switch (state)
    {
        case MODULE_STATE_INIT:
        {
            state = MODULE_STATE_ERROR;

            sockh = socket(initData.sockAddr.sin_family, SOCK_DGRAM, IPPROTO_UDP);

            if (sockh < 0)
            {
                break;
            }

            printf("opening socket %d\n", sockh);

            /* Fall through */
        }

        case MODULE_STATE_SOCKET_WAITING:
        {
            errno = 0;
            if (-1 == connect(sockh, (struct sockaddr*)&initData.sockAddr, sizeof(initData.sockAddr)))
            {
                if (EINPROGRESS == errno)
                {
                    printf("connection in progress\n");
                    state = MODULE_STATE_CONNECTING;
                }
                else if (EAGAIN == errno)
                {
                    printf("socket not ready try again\n");
                    state = MODULE_STATE_SOCKET_WAITING;
                }
                else
                {
                    printf("connect failed, errno is %d\n", errno);
                    state = MODULE_STATE_ERROR;
                }
            }
            else
            {
                printf("socket connected\n");
                state = MODULE_STATE_CONNECTED;
            }

            break;
        }

        case MODULE_STATE_CONNECTING:
        {
            struct pollfd fd;

            fd.fd     = sockh;
            fd.events = POLLOUT;

            if (-1 == poll(&fd, 1, 0))
            {
                state = MODULE_STATE_ERROR;
                break;
            }

            if (0 != (fd.revents & POLLERR))
            {
                printf("connect failed\n");
                state = MODULE_STATE_ERROR;
            }

            if (0 != (fd.revents & POLLOUT))
            {
                printf("socket connected\n");
                state = MODULE_STATE_CONNECTED;

                send(sockh, "Hello\n", 6, 0);
            }

            break;
        }

        case MODULE_STATE_CONNECTED:
        {
            struct pollfd fd;
            ssize_t numBytes = 0;
            uint8_t buffer[128];

            fd.fd     = sockh;
            fd.events = POLLIN|POLLOUT;

            if (-1 == poll(&fd, 1, 0))
            {
                state = MODULE_STATE_ERROR;
                break;
            }

            if (0 != (fd.revents & POLLIN))
            {
                union sockaddr_union sockAddr;
                socklen_t fromLen = sizeof(sockAddr);
                char ipStr[64];

                errno = 0;
                numBytes = recvfrom(sockh, NULL, 0, MSG_PEEK|MSG_TRUNC, NULL, NULL);

                if ((numBytes <= 0) && (errno != EWOULDBLOCK))
                {
                    state = MODULE_STATE_DISCONNECTED;
                    break;
                }

                if (numBytes >= sizeof(buffer))
                {
                    numBytes = sizeof(buffer);
                }

                errno = 0;
                numBytes = recvfrom(sockh, buffer, numBytes, 0, (struct sockaddr*)&sockAddr, &fromLen);
                if (numBytes <= 0)
                {
                    if (errno != EWOULDBLOCK)
                    {
                        printf("recv failed, errno is %d\n", errno);
                        state = MODULE_STATE_DISCONNECTED;
                        break;
                    }
                }

                if (AF_INET == sockAddr.sin_family)
                {
                    inet_ntop(sockAddr.sin_family, &sockAddr.in4.sin_addr, ipStr, sizeof(ipStr));
                }
                else if (AF_INET6 == sockAddr.sin_family)
                {
                    inet_ntop(sockAddr.sin_family, &sockAddr.in6.sin6_addr, ipStr, sizeof(ipStr));
                }

                printf("recv: %d from %s:%d\n", numBytes, ipStr, ntohs(sockAddr.sin_port));
            }

            if (0 != (fd.revents & POLLOUT))
            {
                if (numBytes > 0)
                {
                    errno = 0;
                    numBytes = send(sockh, buffer, numBytes, 0);

                    if ((numBytes < 0) && (errno != EWOULDBLOCK) && (errno != EAGAIN))
                    {
                        printf("send failed, errno is %d\n", errno);
                        state = MODULE_STATE_DISCONNECTED;
                        break;
                    }
                }
            }

            break;
        }

        case MODULE_STATE_DISCONNECTED:
        {
            if (0 != sockh)
            {
                shutdown(sockh, SHUT_RDWR);
                sockh = 0;
            }
            break;
        }

        case MODULE_STATE_ERROR:
        {
            break;
        }

        default:
        {
            break;
        }
    }
}