ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen) { int ret; ssize_t n; while ((n = g_sys_recvfrom(sockfd, buf, len, flags, src_addr, addrlen)) < 0) { if (EINTR == errno) continue; if (!fd_not_ready()) return -1; ret = add_fd_event(sockfd, EVENT_READABLE, event_rw_callback, current_coro()); if (ret) return -2; schedule_timeout(RECVFROM_TIMEOUT); del_fd_event(sockfd, EVENT_READABLE); if (is_wakeup_by_timeout()) { errno = ETIME; return -3; } } return n; }
ssize_t writev(int fd, const struct iovec *iov, int iovcnt) { int ret; ssize_t n; while ((n = g_sys_writev(fd, iov, iovcnt)) < 0) { if (EINTR == errno) continue; if (!fd_not_ready()) return -1; ret = add_fd_event(fd, EVENT_WRITABLE, event_rw_callback, current_coro()); if (ret) return -2; schedule_timeout(WRITEV_TIMEOUT); del_fd_event(fd, EVENT_WRITABLE); if (is_wakeup_by_timeout()) { errno = ETIME; return -3; } } return n; }
ssize_t write(int fd, const void *buf, size_t count) { ssize_t n; while ((n = g_sys_write(fd, buf, count)) < 0) { if (EINTR == errno) continue; if (!fd_not_ready()) return -1; if (add_fd_event(fd, EVENT_WRITABLE, event_rw_callback, current_coro())) return -2; schedule_timeout(WRITE_TIMEOUT); del_fd_event(fd, EVENT_WRITABLE); if (is_wakeup_by_timeout()) { errno = ETIME; return -3; } } return n; }
ssize_t read(int fd, void *buf, size_t count) { int ret; ssize_t n; while ((n = g_sys_read(fd, buf, count)) < 0) { if (EINTR == errno) continue; if (!fd_not_ready()) return -1; ret = add_fd_event(fd, EVENT_READABLE, event_rw_callback, current_coro()); if (ret) return -2; schedule_timeout(READ_TIMEOUT); del_fd_event(fd, EVENT_READABLE); if (is_wakeup_by_timeout()) { errno = ETIME; return -3; } } return n; }
static void do_accept( struct event_info *ei, void *d ) { struct listener *listener = (struct listener *)d; int fd, addrlen; struct sockaddr_un addr; struct ctl_sock *cs; addrlen = sizeof( addr ); if( ( fd = accept( listener->fd, (struct sockaddr *)&addr, &addrlen ) ) < 0 ) { spook_log( SL_WARN, "error accepting control connection: %s", strerror( errno ) ); return; } spook_log( SL_DEBUG, "accepted control connection" ); cs = (struct ctl_sock *)malloc( sizeof( struct ctl_sock ) ); if( ! cs ) { spook_log( SL_ERR, "out of memory on malloc ctl_sock" ); close( fd ); return; } cs->fd = fd; cs->read_event = add_fd_event( fd, 0, 0, do_read, cs ); }
ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags) { int ret; ssize_t n; while ((n = g_sys_sendmsg(sockfd, msg, flags)) < 0) { if (EINTR == errno) continue; if (!fd_not_ready()) return -1; ret = add_fd_event(sockfd, EVENT_WRITABLE, event_rw_callback, current_coro()); if (ret) return -2; schedule_timeout(SENDMSG_TIMEOUT); del_fd_event(sockfd, EVENT_WRITABLE); if (is_wakeup_by_timeout()) { errno = ETIME; return -3; } } return n; }
ssize_t sendfile_timeout(int out_fd, int in_fd, off_t *offset, size_t count, int timeout) { int ret; ssize_t n; while ((n = sendfile(out_fd, in_fd, offset, count)) < 0) { if (EINTR == errno) continue; if (!fd_not_ready()) return -1; ret = add_fd_event(out_fd, EVENT_WRITABLE, event_rw_callback, current_coro()); if (ret) return -2; schedule_timeout(timeout * 1000); del_fd_event(out_fd, EVENT_WRITABLE); if (is_wakeup_by_timeout()) { errno = ETIME; return -3; } } return n; }
/* in_fd一般就是文件fd, out_fd一定要是远端连接fd */ ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count) { ssize_t n; while ((n = g_sys_sendfile(out_fd, in_fd, offset, count)) < 0) { if (EINTR == errno) continue; if (!fd_not_ready()) return -1; if (add_fd_event(out_fd, EVENT_WRITABLE, event_rw_callback, current_coro())) return -2; schedule_timeout(SENDFILE_TIMEOUT); del_fd_event(out_fd, EVENT_WRITABLE); if (is_wakeup_by_timeout()) { errno = ETIME; return -3; } } return n; }
ssize_t send(int sockfd, const void *buf, size_t len, int flags) { ssize_t n; while ((n = g_sys_send(sockfd, buf, len, flags)) < 0) { if (EINTR == errno) continue; if (!fd_not_ready()) return -1; if (add_fd_event(sockfd, EVENT_WRITABLE, event_rw_callback, current_coro())) return -2; schedule_timeout(SEND_TIMEOUT); del_fd_event(sockfd, EVENT_WRITABLE); if (is_wakeup_by_timeout()) { errno = ETIME; return -3; } } return n; }
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen) { int ret; ssize_t n; while ((n = g_sys_sendto(sockfd, buf, len, flags, dest_addr, addrlen)) < 0) { if (EINTR == errno) continue; if (!fd_not_ready()) return -1; ret = add_fd_event(sockfd, EVENT_WRITABLE, event_rw_callback, current_coro()); if (ret) return -2; schedule_timeout(SENDTO_TIMEOUT); del_fd_event(sockfd, EVENT_WRITABLE); if (is_wakeup_by_timeout()) { errno = ETIME; return -3; } } return n; }
ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags) { ssize_t n; while ((n = g_sys_recvmsg(sockfd, msg, flags)) < 0) { if (EINTR == errno) continue; if (!fd_not_ready()) return -1; if (add_fd_event(sockfd, EVENT_READABLE, event_rw_callback, current_coro())) return -2; schedule_timeout(RECVMSG_TIMEOUT); del_fd_event(sockfd, EVENT_READABLE); if (is_wakeup_by_timeout()) { errno = ETIME; return -3; } } return n; }
static void can_read (void *s, int length) { struct tcp_map *map = (struct tcp_map *) s; if (!map->e_fd_write) map->e_fd_write = add_fd_event (map->fd, 1, handle_fd_can_write, map); }
static void output_space (void *s, int space) { struct tcp_map *map = (struct tcp_map *) s; if (space > 0 && !map->e_fd_read) map->e_fd_read = add_fd_event (map->fd, 0, handle_fd_can_read, map); }
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) { int ret; int connfd = 0; while ((connfd = g_sys_accept(sockfd, addr, addrlen)) < 0) { if (EINTR == errno) continue; if (!fd_not_ready()) return -1; ret = add_fd_event(sockfd, EVENT_READABLE, event_conn_callback, current_coro()); if (ret) return -2; schedule_timeout(ACCEPT_TIMEOUT); del_fd_event(sockfd, EVENT_READABLE); if (is_wakeup_by_timeout()) { errno = ETIME; return -3; } } ret = set_nonblock(connfd); if (ret) { close(connfd); return -4; } ret = enable_tcp_no_delay(connfd); if (ret) { close(connfd); return -5; } ret = set_keep_alive(connfd, KEEP_ALIVE); if (ret) { close(connfd); return -6; } return connfd; }
static void incoming (struct tcb *t, void **d, FILE * fp) { struct tcp_map *map; struct sockaddr_in addr; map = ALLOC (sizeof (struct tcp_map)); fprintf (stderr, "number of TCP maps: %d\n", ++num_tcp_maps); map->next = tlist; map->prev = NULL; if (map->next) map->next->prev = map; tlist = map; map->fp = fp; map->tcb = t; map->e_fd_read = map->e_fd_write = NULL; *d = map; addr.sin_family = AF_INET; memcpy (&addr.sin_addr.s_addr, tcp_get_laddr (t) + 12, 4); addr.sin_port = htons (tcp_get_lport (t)); map->fd = socket (PF_INET, SOCK_STREAM, 0); if (map->fd < 0) { perror ("socket"); tcp_close (t, 0); kill_map (map); return; } fcntl (map->fd, F_SETFL, O_NONBLOCK); if (connect (map->fd, (struct sockaddr *) &addr, sizeof (addr)) < 0) { if (errno == EINPROGRESS) { map->e_fd_write = add_fd_event (map->fd, 1, handle_fd_did_connect, map); } else { perror ("connect"); tcp_close (t, 0); kill_map (map); } } else tcp_accept (t); }
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) { int ret; int flags; socklen_t len; set_nonblock(sockfd); /* connect < 0 && errno == EINPROGRESS才需要跟踪fd是否可写 否则其他情形都是错误的, 直接返回 */ ret = g_sys_connect(sockfd, addr, addrlen); if (0 == ret) //succ return 0; if (ret < 0 && errno != EINPROGRESS) return -1; ret = add_fd_event(sockfd, EVENT_WRITABLE, event_conn_callback, current_coro()); if (ret) return -2; schedule_timeout(CONN_TIMEOUT); del_fd_event(sockfd, EVENT_WRITABLE); if (is_wakeup_by_timeout()) { errno = ETIMEDOUT; return -3; } ret = getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &flags, &len); if (ret == -1 || flags || !len) { if (flags) errno = flags; return -4; } return 0; }
int control_listen(void) { struct sockaddr_un addr; struct listener *listener; int fd; addr.sun_family = AF_UNIX; strcpy( addr.sun_path, "spook.sock" ); unlink( addr.sun_path ); if( ( fd = socket( PF_UNIX, SOCK_STREAM, 0 ) ) < 0 ) { spook_log( SL_ERR, "error creating control socket: %s", strerror( errno ) ); return -1; } if( bind( fd, (struct sockaddr *)&addr, sizeof( addr ) ) < 0 ) { spook_log( SL_ERR, "unable to bind control socket: %s", strerror( errno ) ); close( fd ); return -1; } if( listen( fd, 5 ) < 0 ) { spook_log( SL_ERR, "error attempting to listen on control socket: %s", strerror( errno ) ); close( fd ); return -1; } listener = (struct listener *)malloc( sizeof( struct listener ) ); listener->fd = fd; add_fd_event( fd, 0, 0, do_accept, listener ); spook_log( SL_INFO, "listening on control socket %s", addr.sun_path ); return 0; }
/* called directly from iface driver registry */ struct iface * tap_new_if (char *dev, void (*handle_pkt) (struct iface * iface, struct pbuf * pkt)) { struct iface_tap *iface; iface = ALLOC (sizeof (struct iface_tap)); memset (iface, 0, sizeof (struct iface_tap)); iface->fd = get_tun (iface->devname, dev, 1); fcntl (iface->fd, F_SETFL, O_NONBLOCK); ether_setup ((struct iface_ether *) iface); iface->ife.pkt_handler = handle_pkt; iface->ife.send_frame = tap_send_frame; iface->ife.head_size += 4; memcpy (iface->ife.hwaddr, default_mac, 6); iface->ife.iface.mtu = 1280; add_fd_event (iface->fd, 0, tap_read_callback, iface); return (struct iface *) iface; }
/* called directly from iface driver registry */ struct iface * tun_new_if (char *dev, void (*handle_pkt) (struct iface * iface, struct pbuf * pkt)) { struct iface_tun *iface; #ifndef HAVE_LINUX_IF_TUN_H fprintf (stderr, "This version of the tuntap driver doesn't support IPv6 in tun mode.\nPlease use the tap interface.\n"); exit (1); #endif iface = ALLOC (sizeof (struct iface_tun)); iface->fd = get_tun (iface->devname, dev, 0); fcntl (iface->fd, F_SETFL, O_NONBLOCK); iface->pkt_handler = handle_pkt; iface->iface.mtu = 1280; iface->iface.hwaddr_len = 0; iface->iface.get_buffer = tun_get_buf; iface->iface.send_unicast = tun_send; iface->iface.send_multicast = tun_send; add_fd_event (iface->fd, 0, tun_read_callback, iface); return (struct iface *) iface; }