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; }
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; }