int udp_pollsetup(FAR struct socket *psock, FAR struct pollfd *fds) { FAR struct udp_conn_s *conn = psock->s_conn; FAR struct udp_poll_s *info; FAR struct devif_callback_s *cb; net_lock_t flags; int ret; /* Sanity check */ #ifdef CONFIG_DEBUG if (!conn || !fds) { return -EINVAL; } #endif /* Allocate a container to hold the poll information */ info = (FAR struct udp_poll_s *)kmm_malloc(sizeof(struct udp_poll_s)); if (!info) { return -ENOMEM; } /* Some of the following must be atomic */ flags = net_lock(); /* Get the device that will provide the provide the NETDEV_DOWN event. * NOTE: in the event that the local socket is bound to INADDR_ANY, the * dev value will be zero and there will be no NETDEV_DOWN notifications. */ info->dev = udp_find_laddr_device(conn); /* Setup the UDP remote connection */ ret = udp_connect(conn, NULL); if (ret) { goto errout_with_lock; } /* Allocate a TCP/IP callback structure */ cb = udp_callback_alloc(info->dev, conn); if (!cb) { ret = -EBUSY; goto errout_with_lock; } /* Initialize the poll info container */ info->psock = psock; info->fds = fds; info->cb = cb; /* Initialize the callback structure. Save the reference to the info * structure as callback private data so that it will be available during * callback processing. */ cb->flags = 0; cb->priv = (FAR void *)info; cb->event = udp_poll_interrupt; if ((info->fds->events & POLLOUT) != 0) { cb->flags |= UDP_POLL; } if ((info->fds->events & POLLIN) != 0) { cb->flags |= UDP_NEWDATA; } if ((info->fds->events & (POLLHUP | POLLERR)) != 0) { cb->flags |= NETDEV_DOWN; } /* Save the reference in the poll info structure as fds private as well * for use during poll teardown as well. */ fds->priv = (FAR void *)info; /* Check for read data availability now */ if (!IOB_QEMPTY(&conn->readahead)) { /* Normal data may be read without blocking. */ fds->revents |= (POLLRDNORM & fds->events); } /* Check if any requested events are already in effect */ if (fds->revents != 0) { /* Yes.. then signal the poll logic */ sem_post(fds->sem); } net_unlock(flags); return OK; errout_with_lock: kmm_free(info); net_unlock(flags); return ret; }
int tcp_pollsetup(FAR struct socket *psock, FAR struct pollfd *fds) { FAR struct tcp_conn_s *conn = psock->s_conn; FAR struct tcp_poll_s *info; FAR struct devif_callback_s *cb; net_lock_t flags; int ret; /* Sanity check */ #ifdef CONFIG_DEBUG if (!conn || !fds) { return -EINVAL; } #endif /* Allocate a container to hold the poll information */ info = (FAR struct tcp_poll_s *)kmm_malloc(sizeof(struct tcp_poll_s)); if (!info) { return -ENOMEM; } /* Some of the following must be atomic */ flags = net_lock(); /* Allocate a TCP/IP callback structure */ cb = tcp_callback_alloc(conn); if (!cb) { ret = -EBUSY; goto errout_with_lock; } /* Initialize the poll info container */ info->psock = psock; info->fds = fds; info->cb = cb; /* Initialize the callback structure. Save the reference to the info * structure as callback private data so that it will be available during * callback processing. */ cb->flags = (TCP_NEWDATA | TCP_BACKLOG | TCP_POLL | TCP_CLOSE | TCP_ABORT | TCP_TIMEDOUT); cb->priv = (FAR void *)info; cb->event = tcp_poll_interrupt; /* Save the reference in the poll info structure as fds private as well * for use durring poll teardown as well. */ fds->priv = (FAR void *)info; #ifdef CONFIG_NET_TCPBACKLOG /* Check for read data or backlogged connection availability now */ if (!IOB_QEMPTY(&conn->readahead) || tcp_backlogavailable(conn)) #else /* Check for read data availability now */ if (!IOB_QEMPTY(&conn->readahead)) #endif { /* Normal data may be read without blocking. */ fds->revents |= (POLLRDNORM & fds->events); } /* Check for a loss of connection events. We need to be careful here. * There are four possibilities: * * 1) The socket is connected and we are waiting for data availability * events. * * __SS_ISCONNECTED(f) == true * __SS_ISLISTENING(f) == false * __SS_ISCLOSED(f) == false * * Action: Wait for data availability events * * 2) This is a listener socket that was never connected and we are * waiting for connection events. * * __SS_ISCONNECTED(f) == false * __SS_ISLISTENING(f) == true * __SS_ISCLOSED(f) == false * * Action: Wait for connection events * * 3) This socket was previously connected, but the peer has gracefully * closed the connection. * * __SS_ISCONNECTED(f) == false * __SS_ISLISTENING(f) == false * __SS_ISCLOSED(f) == true * * Action: Return with POLLHUP|POLLERR events * * 4) This socket was previously connected, but we lost the connection * due to some exceptional event. * * __SS_ISCONNECTED(f) == false * __SS_ISLISTENING(f) == false * __SS_ISCLOSED(f) == false * * Action: Return with POLLHUP|POLLERR events */ if (!_SS_ISCONNECTED(psock->s_flags) && !_SS_ISLISTENING(psock->s_flags)) { /* We were previously connected but lost the connection either due * to a graceful shutdown by the remote peer or because of some * exceptional event. */ fds->revents |= (POLLERR | POLLHUP); } /* Check if any requested events are already in effect */ if (fds->revents != 0) { /* Yes.. then signal the poll logic */ sem_post(fds->sem); } net_unlock(flags); return OK; errout_with_lock: kmm_free(info); net_unlock(flags); return ret; }
int icmp_pollsetup(FAR struct socket *psock, FAR struct pollfd *fds) { FAR struct icmp_conn_s *conn = psock->s_conn; FAR struct icmp_poll_s *info; FAR struct devif_callback_s *cb; int ret; DEBUGASSERT(conn != NULL && fds != NULL); /* Allocate a container to hold the poll information */ info = (FAR struct icmp_poll_s *)kmm_malloc(sizeof(struct icmp_poll_s)); if (!info) { return -ENOMEM; } /* Some of the following must be atomic */ net_lock(); /* Get the device that will provide the provide the NETDEV_DOWN event. * NOTE: in the event that the local socket is bound to INADDR_ANY, the * dev value will be zero and there will be no NETDEV_DOWN notifications. */ if (conn->dev == NULL) { conn->dev = netdev_default(); } /* Allocate a ICMP callback structure */ cb = icmp_callback_alloc(conn->dev); if (cb == NULL) { ret = -EBUSY; goto errout_with_lock; } /* Initialize the poll info container */ info->psock = psock; info->fds = fds; info->cb = cb; /* Initialize the callback structure. Save the reference to the info * structure as callback private data so that it will be available during * callback processing. */ cb->flags = 0; cb->priv = (FAR void *)info; cb->event = icmp_poll_eventhandler; if ((info->fds->events & POLLOUT) != 0) { cb->flags |= ICMP_POLL; } if ((info->fds->events & POLLIN) != 0) { cb->flags |= ICMP_NEWDATA; } if ((info->fds->events & (POLLHUP | POLLERR)) != 0) { cb->flags |= NETDEV_DOWN; } /* Save the reference in the poll info structure as fds private as well * for use during poll teardown as well. */ fds->priv = (FAR void *)info; /* Check for read data availability now */ if (!IOB_QEMPTY(&conn->readahead)) { /* Normal data may be read without blocking. */ fds->revents |= (POLLRDNORM & fds->events); } /* Check if any requested events are already in effect */ if (fds->revents != 0) { /* Yes.. then signal the poll logic */ nxsem_post(fds->sem); } net_unlock(); return OK; errout_with_lock: kmm_free(info); net_unlock(); return ret; }