#include <string.h>
#include "winc_socket.h"
#define TCP_SERVER_MAX_CLIENTS 2
typedef enum
{
MODULE_STATE_INIT,
MODULE_STATE_SOCKET_WAITING,
MODULE_STATE_LISTEN,
MODULE_STATE_LISTENING,
MODULE_STATE_ERROR,
} MODULE_STATE;
typedef struct
{
union sockaddr_union sockAddr;
} BSOCK_TCP_SERVER_INIT_TYPE;
static MODULE_STATE state;
static int sockh;
static int sockhClient[TCP_SERVER_MAX_CLIENTS] = {0};
static BSOCK_TCP_SERVER_INIT_TYPE initData = {0};
void bsock_tcp_server_init(void *pInitData)
{
if (NULL != pInitData)
{
memcpy(&initData, pInitData, sizeof(BSOCK_TCP_SERVER_INIT_TYPE));
}
state = MODULE_STATE_INIT;
}
void bsock_tcp_server_run(void)
{
switch (state)
{
case MODULE_STATE_INIT:
{
state = MODULE_STATE_ERROR;
sockh = socket(initData.sockAddr.sin_family, SOCK_STREAM, IPPROTO_TCP);
if (sockh < 0)
{
break;
}
printf("opening socket %d\n", sockh);
}
case MODULE_STATE_SOCKET_WAITING:
{
errno = 0;
if (-1 == bind(sockh, (struct sockaddr*)&initData.sockAddr, sizeof(initData.sockAddr)))
{
printf("bind failed, errno is %d\n", errno);
state = MODULE_STATE_ERROR;
break;
}
printf("socket bound\n");
}
case MODULE_STATE_LISTEN:
{
errno = 0;
if (-1 == listen(sockh, TCP_SERVER_MAX_CLIENTS))
{
if (EAGAIN == errno)
{
printf("socket not ready try again\n");
state = MODULE_STATE_LISTEN;
}
else
{
printf("listen failed, errno is %d\n", errno);
state = MODULE_STATE_ERROR;
}
}
else
{
printf("socket listening\n");
state = MODULE_STATE_LISTENING;
}
break;
}
case MODULE_STATE_LISTENING:
{
int i;
int numfds = 1;
struct pollfd fd[1+TCP_SERVER_MAX_CLIENTS] = {0};
fd[0].fd = sockh;
fd[0].events = POLLIN;
for (i=0; i<TCP_SERVER_MAX_CLIENTS; i++)
{
fd[i+1].fd = sockhClient[i];
if (0 != fd[i+1].fd)
{
fd[i+1].events = POLLIN|POLLOUT;
numfds++;
}
}
if (-1 == poll(fd, numfds, 0))
{
state = MODULE_STATE_ERROR;
break;
}
if (0 != (fd[0].revents & POLLIN))
{
for (i=0; i<TCP_SERVER_MAX_CLIENTS; i++)
{
union sockaddr_union sockAddr;
socklen_t sockAddrLen = sizeof(union sockaddr_union);
char ipStr[64];
if (0 == sockhClient[i])
{
sockhClient[i] = accept(sockh, (struct sockaddr*)&sockAddr, &sockAddrLen);
if (-1 == sockhClient[i])
{
sockhClient[i] = 0;
}
else
{
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("accept %d from %s:%d\n", sockhClient[i], ipStr, ntohs(sockAddr.sin_port));
}
break;
}
}
}
for (i=1; i<=TCP_SERVER_MAX_CLIENTS; i++)
{
if ((0 != fd[i].fd) && (0 != fd[i].revents))
{
ssize_t numBytes = 0;
uint8_t buffer[128];
if (0 != (fd[i].revents & POLLIN))
{
errno = 0;
numBytes = recv(fd[i].fd, NULL, 0, MSG_PEEK|MSG_TRUNC);
if ((numBytes <= 0) && (errno != EWOULDBLOCK))
{
shutdown(fd[i].fd, SHUT_RDWR);
sockhClient[i-1] = 0;
break;
}
if (numBytes >= sizeof(buffer))
{
numBytes = sizeof(buffer);
}
errno = 0;
numBytes = recv(fd[i].fd, buffer, numBytes, 0);
if (numBytes <= 0)
{
if (errno != EWOULDBLOCK)
{
printf("recv failed, errno is %d\n", errno);
shutdown(fd[i].fd, SHUT_RDWR);
sockhClient[i-1] = 0;
break;
}
}
printf("recv: %d\n", numBytes);
}
if (0 != (fd[i].revents & POLLHUP))
{
printf("socket disconnected\n");
if (0 == (fd[i].revents & POLLIN))
{
shutdown(fd[i].fd, SHUT_RDWR);
sockhClient[i-1] = 0;
break;
}
}
if (0 != (fd[i].revents & POLLOUT))
{
if (numBytes > 0)
{
errno = 0;
numBytes = send(fd[i].fd, buffer, numBytes, 0);
if ((numBytes < 0) && (errno != EWOULDBLOCK) && (errno != EAGAIN))
{
printf("send failed, errno is %d\n", errno);
shutdown(fd[i].fd, SHUT_RDWR);
sockhClient[i-1] = 0;
break;
}
}
}
}
}
break;
}
case MODULE_STATE_ERROR:
{
break;
}
default:
{
break;
}
}
}