static void citp_passthrough_dtor(citp_fdinfo* fdi, int fdt_locked) { citp_alien_fdi* epi = fdi_to_alien_fdi(fdi); CITP_FDTABLE_LOCK(); ci_tcp_helper_close_no_trampoline(epi->os_socket); __citp_fdtable_reserve(epi->os_socket, 0); CITP_FDTABLE_UNLOCK(); citp_netif_release_ref(fdi_to_alien_fdi(fdi)->netif, fdt_locked); }
int citp_passthrough_accept(citp_fdinfo* fdi, struct sockaddr* sa, socklen_t* p_sa_len, int flags, citp_lib_context_t* lib_context) { #if CI_LIBC_HAS_accept4 return ci_sys_accept4(fdi_to_alien_fdi(fdi)->os_socket, sa, p_sa_len, flags); #else ci_assert_equal(flags, 0); return ci_sys_accept(fdi_to_alien_fdi(fdi)->os_socket, sa, p_sa_len); #endif }
static int citp_passthrough_getsockopt(citp_fdinfo* fdi, int level, int optname, void* optval, socklen_t* optlen) { return ci_sys_getsockopt(fdi_to_alien_fdi(fdi)->os_socket, level, optname, optval, optlen); }
static int citp_passthrough_getpeername(citp_fdinfo* fdi, struct sockaddr* sa, socklen_t* p_sa_len) { return ci_sys_getpeername(fdi_to_alien_fdi(fdi)->os_socket, sa, p_sa_len); }
static int citp_passthrough_listen(citp_fdinfo* fdi, int backlog) { int rc = ci_sys_listen(fdi_to_alien_fdi(fdi)->os_socket, backlog); citp_fdinfo_release_ref(fdi, 0); return rc; }
static void citp_fdinfo_do_handover(citp_fdinfo* fdi, int fdt_locked) { int rc; citp_fdinfo* epoll_fdi = NULL; int os_fd = fdi->fd; #ifndef NDEBUG /* Yuk: does for UDP too. */ volatile citp_fdinfo_p* p_fdip; p_fdip = &citp_fdtable.table[fdi->fd].fdip; ci_assert(fdip_is_busy(*p_fdip)); #endif Log_V(ci_log("%s: fd=%d nonb_switch=%d", __FUNCTION__, fdi->fd, fdi->on_rcz.handover_nonb_switch)); if( fdi->epoll_fd >= 0 ) { epoll_fdi = citp_epoll_fdi_from_member(fdi, fdt_locked); if( epoll_fdi->protocol->type == CITP_EPOLLB_FD ) citp_epollb_on_handover(epoll_fdi, fdi); } rc = fdtable_fd_move(fdi->fd, OO_IOC_TCP_HANDOVER); if( rc == -EBUSY && fdi->epoll_fd >= 0 ) { ci_assert(fdi_to_sock_fdi(fdi)->sock.s->b.sb_aflags & CI_SB_AFLAG_MOVED_AWAY); /* If this is our epoll, we can do full handover: we manually add os * fd into the epoll set. * Fixme: ensure we are not in _other_ epoll sets */ ci_bit_clear(&fdi_to_sock_fdi(fdi)->sock.s->b.sb_aflags, CI_SB_AFLAG_MOVED_AWAY_IN_EPOLL_BIT); rc = fdtable_fd_move(fdi->fd, OO_IOC_FILE_MOVED); } if( rc != 0 ) { citp_fdinfo* new_fdi; if( ! fdt_locked ) CITP_FDTABLE_LOCK(); new_fdi = citp_fdtable_probe_locked(fdi->fd, CI_TRUE, CI_TRUE); citp_fdinfo_release_ref(new_fdi, 1); if( ! fdt_locked ) CITP_FDTABLE_UNLOCK(); ci_assert_equal(citp_fdinfo_get_type(new_fdi), CITP_PASSTHROUGH_FD); os_fd = fdi_to_alien_fdi(new_fdi)->os_socket; } if( fdi->on_rcz.handover_nonb_switch >= 0 ) { int on_off = !! fdi->on_rcz.handover_nonb_switch; int rc = ci_sys_ioctl(os_fd, FIONBIO, &on_off); if( rc < 0 ) Log_E(ci_log("%s: ioctl failed on_off=%d", __FUNCTION__, on_off)); } if( rc != 0 ) goto exit; citp_fdtable_busy_clear(fdi->fd, fdip_passthru, fdt_locked); exit: citp_fdinfo_get_ops(fdi)->dtor(fdi, fdt_locked); if( epoll_fdi != NULL && epoll_fdi->protocol->type == CITP_EPOLL_FD ) citp_epoll_on_handover(epoll_fdi, fdi, fdt_locked); if( epoll_fdi != NULL ) citp_fdinfo_release_ref(epoll_fdi, fdt_locked); citp_fdinfo_free(fdi); }
int citp_passthrough_bind(citp_fdinfo* fdi, const struct sockaddr* sa, socklen_t sa_len) { int rc = ci_sys_bind(fdi_to_alien_fdi(fdi)->os_socket, sa, sa_len); citp_fdinfo_release_ref(fdi, 0); return rc; }
static int citp_passthrough_setsockopt(citp_fdinfo* fdi, int level, int optname, const void* optval, socklen_t optlen) { int rc = ci_sys_setsockopt(fdi_to_alien_fdi(fdi)->os_socket, level, optname, optval, optlen); citp_fdinfo_release_ref(fdi, 0); return rc; }
static int citp_passthrough_connect(citp_fdinfo* fdi, const struct sockaddr* sa, socklen_t sa_len, citp_lib_context_t* lib_context) { int rc = ci_sys_connect(fdi_to_alien_fdi(fdi)->os_socket, sa, sa_len); citp_fdinfo_release_ref(fdi, 0); return rc; }
static int citp_passthrough_sendmmsg(citp_fdinfo* fdinfo, struct mmsghdr* mmsg, unsigned vlen, int flags) { #ifdef OO_SENDMMSG_NOT_IN_LIBC errno = ENOSYS; return -1; #else return ci_sys_sendmmsg(fdi_to_alien_fdi(fdinfo)->os_socket, mmsg, vlen, flags); #endif }
static int citp_passthrough_recvmmsg(citp_fdinfo* fdi, struct mmsghdr* msg, unsigned vlen, int flags, ci_recvmmsg_timespec* timeout) { #ifdef OO_RECVMMSG_NOT_IN_LIBC errno = ENOSYS; return -1; #else return ci_sys_recvmmsg(fdi_to_alien_fdi(fdi)->os_socket, msg, vlen, flags, timeout); #endif }
static int citp_passthrough_shutdown(citp_fdinfo* fdi, int how) { return ci_sys_shutdown(fdi_to_alien_fdi(fdi)->os_socket, how); }
static int citp_passthrough_ioctl(citp_fdinfo* fdi, int request, void* arg) { return ci_sys_ioctl(fdi_to_alien_fdi(fdi)->os_socket, request, arg); }
static int citp_passthrough_send(citp_fdinfo* fdi, const struct msghdr* msg, int flags) { return ci_sys_sendmsg(fdi_to_alien_fdi(fdi)->os_socket, msg, flags); }