static struct passive_context * create_passive(struct ev_loop *loop, struct server_config *cfg) { struct passive_context *passive = NULL; struct uinet_socket *listener = NULL; struct ev_uinet_ctx *soctx = NULL; struct uinet_in_addr addr; int optlen, optval; int error; struct uinet_sockaddr_in sin; if (uinet_inet_pton(UINET_AF_INET, cfg->listen_addr, &addr) <= 0) { printf("Malformed address %s\n", cfg->listen_addr); goto fail; } error = uinet_socreate(UINET_PF_INET, &listener, UINET_SOCK_STREAM, 0); if (0 != error) { printf("Listen socket creation failed (%d)\n", error); goto fail; } soctx = ev_uinet_attach(listener); if (NULL == soctx) { printf("Failed to alloc libev socket context\n"); goto fail; } if ((error = uinet_make_socket_passive(listener))) { printf("Failed to make listen socket passive (%d)\n", error); goto fail; } if (cfg->interface->promisc) { if ((error = uinet_make_socket_promiscuous(listener, cfg->interface->cdom))) { printf("Failed to make listen socket promiscuous (%d)\n", error); goto fail; } } /* * The following settings will be inherited by all sockets created * by this listen socket. */ /* * Need to be non-blocking to work with the event system. */ uinet_sosetnonblocking(listener, 1); /* Wait 5 seconds for connections to complete */ optlen = sizeof(optval); optval = 5; if ((error = uinet_sosetsockopt(listener, UINET_IPPROTO_TCP, UINET_TCP_KEEPINIT, &optval, optlen))) goto fail; /* Begin counting down to close after 10 seconds of idle */ optlen = sizeof(optval); optval = 10; if ((error = uinet_sosetsockopt(listener, UINET_IPPROTO_TCP, UINET_TCP_KEEPIDLE, &optval, optlen))) goto fail; /* Count down to close once per second */ optlen = sizeof(optval); optval = 1; if ((error = uinet_sosetsockopt(listener, UINET_IPPROTO_TCP, UINET_TCP_KEEPINTVL, &optval, optlen))) goto fail; /* Close after idle for 3 counts */ optlen = sizeof(optval); optval = 3; if ((error = uinet_sosetsockopt(listener, UINET_IPPROTO_TCP, UINET_TCP_KEEPCNT, &optval, optlen))) goto fail; /* Wait 100 milliseconds for missing TCP segments */ optlen = sizeof(optval); optval = 100; if ((error = uinet_sosetsockopt(listener, UINET_IPPROTO_TCP, UINET_TCP_REASSDL, &optval, optlen))) goto fail; passive = calloc(1, sizeof(struct passive_context)); if (NULL == passive) { goto fail; } passive->loop = loop; passive->listener = listener; passive->verbose = cfg->verbose; passive->interface = cfg->interface; passive->extract = cfg->extract; memcpy(passive->content_types, cfg->content_types, sizeof(passive->content_types)); memset(&sin, 0, sizeof(struct uinet_sockaddr_in)); sin.sin_len = sizeof(struct uinet_sockaddr_in); sin.sin_family = UINET_AF_INET; sin.sin_addr = addr; sin.sin_port = htons(cfg->listen_port); error = uinet_sobind(listener, (struct uinet_sockaddr *)&sin); if (0 != error) { printf("bind failed\n"); goto fail; } error = uinet_solisten(passive->listener, -1); if (0 != error) goto fail; if (passive->verbose) { char buf[32]; printf("Listening on %s:%u\n", uinet_inet_ntoa(addr, buf, sizeof(buf)), cfg->listen_port); } ev_init(&passive->listen_watcher, accept_cb); ev_uinet_set(&passive->listen_watcher, soctx, EV_READ); passive->listen_watcher.data = passive; ev_uinet_start(loop, &passive->listen_watcher); return (passive); fail: if (soctx) ev_uinet_detach(soctx); if (listener) uinet_soclose(listener); if (passive) free(passive); return (NULL); }
static int passive_start(struct uinet_demo_config *cfg, uinet_instance_t uinst, struct ev_loop *loop) { struct uinet_demo_passive *passive = (struct uinet_demo_passive *)cfg; struct uinet_socket *listen_socket = NULL; struct ev_uinet_ctx *soctx = NULL; struct uinet_in_addr addr; int optlen, optval; int error; struct uinet_sockaddr_in sin; if (uinet_inet_pton(UINET_AF_INET, passive->listen_addr, &addr) <= 0) { printf("%s: Malformed address %s\n", passive->cfg.name, passive->listen_addr); error = UINET_EINVAL; goto fail; } error = uinet_socreate(passive->cfg.uinst, UINET_PF_INET, &listen_socket, UINET_SOCK_STREAM, 0); if (0 != error) { printf("%s: Listen socket creation failed (%d)\n", passive->cfg.name, error); goto fail; } soctx = ev_uinet_attach(listen_socket); if (NULL == soctx) { printf("%s: Failed to alloc libev socket context\n", passive->cfg.name); error = UINET_ENOMEM; goto fail; } if ((error = uinet_make_socket_passive(listen_socket))) { printf("%s: Failed to make listen socket passive (%d)\n", passive->cfg.name, error); goto fail; } if (passive->promisc) { if ((error = uinet_make_socket_promiscuous(listen_socket, NULL))) { printf("%s: Failed to make listen socket promiscuous (%d)\n", passive->cfg.name, error); goto fail; } } /* * The following settings will be inherited by all sockets created * by this listen socket. */ /* * Need to be non-blocking to work with the event system. */ uinet_sosetnonblocking(listen_socket, 1); /* Wait 5 seconds for connections to complete */ optlen = sizeof(optval); optval = 5; if ((error = uinet_sosetsockopt(listen_socket, UINET_IPPROTO_TCP, UINET_TCP_KEEPINIT, &optval, optlen))) { printf("%s: Failed to set TCP_KEEPINIT (%d)\n", passive->cfg.name, error); goto fail; } /* Begin counting down to close after 10 seconds of idle */ optlen = sizeof(optval); optval = 10; if ((error = uinet_sosetsockopt(listen_socket, UINET_IPPROTO_TCP, UINET_TCP_KEEPIDLE, &optval, optlen))) { printf("%s: Failed to set TCP_KEEPIDLE (%d)\n", passive->cfg.name, error); goto fail; } /* Count down to close once per second */ optlen = sizeof(optval); optval = 1; if ((error = uinet_sosetsockopt(listen_socket, UINET_IPPROTO_TCP, UINET_TCP_KEEPINTVL, &optval, optlen))) { printf("%s: Failed to set TCP_KEEPINTVL (%d)\n", passive->cfg.name, error); goto fail; } /* Close after idle for 3 counts */ optlen = sizeof(optval); optval = 3; if ((error = uinet_sosetsockopt(listen_socket, UINET_IPPROTO_TCP, UINET_TCP_KEEPCNT, &optval, optlen))) { printf("%s: Failed to set TCP_KEEPCNT (%d)\n", passive->cfg.name, error); goto fail; } /* Wait 100 milliseconds for missing TCP segments */ optlen = sizeof(optval); optval = 100; if ((error = uinet_sosetsockopt(listen_socket, UINET_IPPROTO_TCP, UINET_TCP_REASSDL, &optval, optlen))) { printf("%s: Failed to set TCP_REASSDL (%d)\n", passive->cfg.name, error); goto fail; } passive->listen_socket = listen_socket; memset(&sin, 0, sizeof(struct uinet_sockaddr_in)); sin.sin_len = sizeof(struct uinet_sockaddr_in); sin.sin_family = UINET_AF_INET; sin.sin_addr = addr; sin.sin_port = htons(passive->listen_port); error = uinet_sobind(listen_socket, (struct uinet_sockaddr *)&sin); if (0 != error) { printf("%s: Bind to %s:%u failed\n", passive->cfg.name, passive->listen_addr, passive->listen_port); goto fail; } error = uinet_solisten(passive->listen_socket, -1); if (0 != error) { printf("%s: Listen on %s:%u failed\n", passive->cfg.name, passive->listen_addr, passive->listen_port); goto fail; } if (passive->cfg.verbose) printf("%s: Listening on %s:%u\n", passive->cfg.name, passive->listen_addr, passive->listen_port); ev_init(&passive->listen_watcher, passive_accept_cb); ev_uinet_set(&passive->listen_watcher, soctx, EV_READ); passive->listen_watcher.data = passive; ev_uinet_start(loop, &passive->listen_watcher); return (0); fail: if (soctx) ev_uinet_detach(soctx); if (listen_socket) uinet_soclose(listen_socket); return (error); }