#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <ifaddrs.h>
#include <limits.h>
#include "sock.h"
#include "sock_util.h"
#ifdef HAVE_EPOLL
#include <sys/epoll.h>
#else
#include <poll.h>
#endif
#define SOCK_LOG_DBG(...) _SOCK_LOG_DBG(FI_LOG_EP_CTRL, __VA_ARGS__)
#define SOCK_LOG_ERROR(...) _SOCK_LOG_ERROR(FI_LOG_EP_CTRL, __VA_ARGS__)
#ifdef HAVE_EPOLL
int sock_epoll_create(struct sock_epoll_set *set, int size)
{
int ret;
set->size = size;
set->used = 0;
set->events = calloc(size, sizeof(struct epoll_event));
if (!set->events)
return -FI_ENOMEM;
ret = set->fd = epoll_create(size);
if (ret < 0)
free(set->events);
return ret;
}
int sock_epoll_add(struct sock_epoll_set *set, int fd)
{
int ret;
struct epoll_event event;
memset(&event, 0, sizeof(event));
event.data.fd = fd;
event.events = EPOLLIN;
if (set->used == set->size)
return -1;
ret = epoll_ctl(set->fd, EPOLL_CTL_ADD, fd, &event);
if (!ret)
set->used++;
return ret;
}
int sock_epoll_del(struct sock_epoll_set *set, int fd)
{
int ret;
if (!set->used)
return -1;
ret = epoll_ctl(set->fd, EPOLL_CTL_DEL, fd, NULL);
if (!ret)
set->used--;
return ret;
}
int sock_epoll_wait(struct sock_epoll_set *set, int timeout)
{
if (!set->used)
return 0;
return epoll_wait(set->fd, set->events, set->used, timeout);
}
int sock_epoll_get_fd_at_index(struct sock_epoll_set *set, int index)
{
return set->events[index].data.fd;
}
void sock_epoll_close(struct sock_epoll_set *set)
{
free(set->events);
close(set->fd);
set->used = 0;
}
#else
int sock_epoll_create(struct sock_epoll_set *set, int size)
{
set->size = size;
set->used = 0;
set->pollfds = calloc(size, sizeof(struct pollfd));
return set->pollfds ? 0 : -1;
}
int sock_epoll_add(struct sock_epoll_set *set, int fd)
{
if (set->used == set->size)
return -1;
set->pollfds[set->used].fd = fd;
set->pollfds[set->used].events = POLLIN;
set->used++;
return 0;
}
int sock_epoll_del(struct sock_epoll_set *set, int fd)
{
int i;
for (i = 0; i < set->used; i++) {
if (set->pollfds[i].fd == fd)
break;
}
if (i == set->used)
return -1;
set->pollfds[i].fd = set->pollfds[set->used - 1].fd;
set->used--;
return 0;
}
int sock_epoll_wait(struct sock_epoll_set *set, int timeout)
{
if (!set->used)
return 0;
return poll(set->pollfds, set->used, timeout);
}
int sock_epoll_get_fd_at_index(struct sock_epoll_set *set, int index)
{
int i;
for (i = 0; i < set->used; i++) {
if ((set->pollfds[i].revents & POLLIN)) {
if (index) {
index--;
continue;
} else {
return set->pollfds[i].fd;
}
}
}
return -1;
}
void sock_epoll_close(struct sock_epoll_set *set)
{
free(set->pollfds);
set->used = 0;
}
#endif