static void udps_send_user(TCPIPS* tcpips, IP* src, IO* io, HANDLE handle) { IO* user_io; unsigned int offset, size; UDP_STACK* udp_stack; UDP_HANDLE* uh; UDP_HEADER* hdr = io_data(io); uh = so_get(&tcpips->udps.handles, handle); for (offset = sizeof(UDP_HEADER); uh->head && offset < io->data_size; offset += size) { user_io = udps_peek_head(tcpips, uh); udp_stack = io_push(user_io, sizeof(UDP_STACK)); udp_stack->remote_addr.u32.ip = src->u32.ip; udp_stack->remote_port = be2short(hdr->src_port_be); size = io_get_free(user_io); if (size > io->data_size - offset) size = io->data_size - offset; memcpy(io_data(user_io), (uint8_t*)io_data(io) + offset, size); user_io->data_size = size; io_complete(uh->process, HAL_IO_CMD(HAL_UDP, IPC_READ), handle, user_io); } #if (UDP_DEBUG) if (offset < io->data_size) printf("UDP: %d byte(s) dropped\n", io->data_size - offset); #endif //UDP_DEBUG }
/* Handle io after polling. */ int io_after_poll(struct io *io, struct pollfd *pfd) { /* Ignore NULL ios. */ if (io == NULL) return (1); IO_DEBUG(io, "poll out: 0x%03x", pfd->revents); /* Close on POLLERR or POLLNVAL hard. */ if (pfd->revents & (POLLERR|POLLNVAL)) { io->flags |= IOF_CLOSED; return (0); } /* Close on POLLHUP but only if there is nothing to read. */ if (pfd->revents & POLLHUP && (pfd->revents & POLLIN) == 0) { io->flags |= IOF_CLOSED; return (0); } /* Check for repeated read/write. */ if ((io->flags & (IOF_NEEDPUSH|IOF_NEEDFILL)) != 0) { /* * If a repeated read/write is necessary, the socket must be * ready for both reading and writing */ if (pfd->revents & (POLLOUT|POLLIN)) { if (io->flags & IOF_NEEDPUSH) { switch (io_push(io)) { case 0: io->flags |= IOF_CLOSED; return (0); case -1: return (-1); } } if (io->flags & IOF_NEEDFILL) { switch (io_fill(io)) { case 0: io->flags |= IOF_CLOSED; return (0); case -1: return (-1); } } } return (1); } /* Otherwise try to read and write. */ if (io->wr != NULL && pfd->revents & POLLOUT) { switch (io_push(io)) { case 0: io->flags |= IOF_CLOSED; return (0); case -1: return (-1); } } if (io->rd != NULL && pfd->revents & POLLIN) { switch (io_fill(io)) { case 0: io->flags |= IOF_CLOSED; return (0); case -1: return (-1); } } return (1); }