Пример #1
0
SERVER_HANDLE_V1 *get_mock_server_api(void)
{
    static SERVER_CORE_API core_api = {
        .server_version = mock_get_server_version,
        .hash = mock_hash,
        .realtime = mock_realtime,
        .get_current_time = mock_get_current_time,
        .abstime = mock_abstime,
        .parse_config = mock_parse_config
    };

    static SERVER_COOKIE_API server_cookie_api = {
        .get_auth_data = mock_get_auth_data,
        .store_engine_specific = mock_store_engine_specific,
        .get_engine_specific = mock_get_engine_specific,
        .get_socket_fd = mock_get_socket_fd,
        .set_tap_nack_mode = mock_set_tap_nack_mode,
        .notify_io_complete = mock_notify_io_complete,
        .reserve = mock_cookie_reserve,
        .release = mock_cookie_release
    };

    static SERVER_STAT_API server_stat_api = {
        .new_stats = mock_new_independent_stats,
        .release_stats = mock_release_independent_stats,
        .evicting = mock_count_eviction
    };

    static SERVER_EXTENSION_API extension_api = {
        .register_extension = mock_register_extension,
        .unregister_extension = mock_unregister_extension,
        .get_extension = mock_get_extension
    };

    static SERVER_CALLBACK_API callback_api = {
        .register_callback = mock_register_callback,
        .perform_callbacks = mock_perform_callbacks
    };

    static SERVER_HANDLE_V1 rv = {
        .interface = 1,
        .core = &core_api,
        .stat = &server_stat_api,
        .extension = &extension_api,
        .callback = &callback_api,
        .cookie = &server_cookie_api
    };

    return &rv;
}

void init_mock_server(ENGINE_HANDLE *server_engine) {
    process_started = time(0);
    null_logger = get_null_logger();
    stderr_logger = get_stderr_logger();
    engine = server_engine;
    extensions.logger = null_logger;
}
Пример #2
0
int
main(int argc, char *argv[])
{
    typedef struct ip_list_t {
        char *addr;
        int family;
        struct ip_list_t *next;
    } ip_list_t;
    
    static struct option longopts[] = {
        { "help",      no_argument,       0, 'h' },
        { "version",   no_argument,       0, 'V' },
        { "port",      required_argument, 0, 'p' },
        { "loglevel",  required_argument, 0, 'l' },
        { "interface", required_argument, 0, 'i' },
        { 0,           0,                 0,  0  }
    };

    long loglevel = LOG_NOTICE;
    char *portstr = 0;
    ip_list_t *ip = 0, *listen_ips = 0;
    int ch;
    while ((ch = getopt_long(argc, argv, "hVl:p:i:", longopts, 0)) != -1) {
        switch (ch) {
        case 'V':
            print_version(basename(argv[0]));
            exit(0);
            break;
        case 'l':
            errno = 0;
            loglevel = strtol(optarg, 0, 10);
            if (errno || loglevel < 0 || loglevel > 7) {
                fprintf(stderr, "Log level must be between 0 and 7, inclusive.\n");
                exit(1);
            }
            break;
        case 'p':
            portstr = strdup(optarg);
            if (!portstr) {
                perror("strdup");
                exit(1);
            }
            break;
        case 'i':
            if (ip) {
                ip->next = (ip_list_t *) malloc(sizeof(ip_list_t));
                ip = ip->next;
            } else {
                listen_ips = (ip_list_t *) malloc(sizeof(ip_list_t));
                ip = listen_ips;
            }
            ip->addr = strdup(optarg);
            ip->family = AF_UNSPEC;
            ip->next = 0;
            break;
        case 'h':
        default:
            usage(basename(argv[0]));
            exit(0);
        }
    }

    /*
     * If no listen IPs were specified, listen on all interfaces
     * (i.e., the wildcard address).
     *
     * Regarding IPv4 and IPv6 wildcard binds on the same port:
     *
     * The Linux kernel maps both IPv4 and IPv6 wildcard binds to the
     * same local port space, in which case only one family can be
     * bound to a given port. An IPv6 wildcard bind on a GNU/Linux
     * system will see both IPv4 and IPv6 traffic.
     *
     * BSD-based platforms (e.g., Mac OS X) recommend listening on two
     * sockets for the same port, one for IPv4 and one for IPv6, when
     * you want to accept traffic for both transports, especially when
     * access control (firewalling) is in effect.
     *
     * OpenBSD simply won't route IPv4 traffic to IPv6 sockets; on
     * that platform, an application must bind to both of the IPv4 and
     * IPv6 wildcard addresses to receive both types of traffic.
     */
    
    if (!listen_ips) {
        ip = (ip_list_t *) malloc(sizeof(ip_list_t));
        if (!ip) {
            perror("malloc");
            exit(1);
        }
        listen_ips = ip;
        ip->addr = 0;
        ip->family = AF_INET6;
#ifndef ECHOEV_PLATFORM_LINUX
        ip->next = (ip_list_t *) malloc(sizeof(ip_list_t));
        if (!ip->next) {
            perror("malloc");
            exit(1);
        }
        ip = ip->next;
        ip->addr = 0;
        ip->family = AF_INET;
#endif
        ip->next = 0;
    }
    
    get_stderr_logger(&log, 0, &logmask);
    logmask(LOG_UPTO(loglevel));

    if (ignore_sigpipe() == -1) {
        log(LOG_ERR, "Trying to ignore SIGPIPE, but failed: %m");
        exit(1);
    }
    
    struct ev_loop *loop = EV_DEFAULT;

    struct addrinfo hints, *res;
    memset(&hints, 0, sizeof(hints));
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;
    hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;

    for (ip = listen_ips; ip != 0; ip = ip->next) {
        hints.ai_family = ip->family;
        int err = getaddrinfo(ip->addr,
                              portstr ? portstr : default_portstr,
                              &hints,
                              &res);
        if (err) {
            log(LOG_ERR, "getaddrinfo failed: %s", gai_strerror(err));
            exit(err);
        }
        assert(!res->ai_next);
        listener_io *lio =
            make_listener(res->ai_addr, res->ai_addrlen);
        if (lio) {
            log_with_addr(LOG_NOTICE,
                          "listening on %s",
                          res->ai_addr,
                          res->ai_addrlen);
            ev_io_start(loop, &lio->listener);
        } else {
            log(LOG_ERR, "Can't create listening socket: %m");
            exit(1);
        }
        freeaddrinfo(res);
    }

    /* Clean up before entering ev_run loop */
    if (portstr)
        free(portstr);
    while (listen_ips) {
        ip = listen_ips;
        listen_ips = ip->next;
        free(ip->addr);
        free(ip);
    }
    listen_ips = 0;
    
    log(LOG_DEBUG, "entering ev_run");
    ev_run(loop, 0);

    log(LOG_DEBUG, "ev_run exited");
    return 0;
}