예제 #1
0
파일: mk_socket.c 프로젝트: nokute78/monkey
/* Just IPv4 for now... */
int mk_socket_server(char *port, char *listen_addr,
                     int reuse_port, struct mk_server *server)
{
    int ret;
    int socket_fd = -1;
    struct addrinfo hints;
    struct addrinfo *res, *rp;

    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags = AI_PASSIVE;

    ret = getaddrinfo(listen_addr, port, &hints, &res);
    if(ret != 0) {
        mk_err("Can't get addr info: %s", gai_strerror(ret));
        return -1;
    }

    for (rp = res; rp != NULL; rp = rp->ai_next) {
        socket_fd = mk_socket_create(rp->ai_family,
                                     rp->ai_socktype, rp->ai_protocol);
        if (socket_fd == -1) {
            mk_warn("Error creating server socket, retrying");
            continue;
        }

        ret = mk_socket_set_tcp_nodelay(socket_fd);
        if (ret == -1) {
            mk_warn("Could not set TCP_NODELAY");
        }

        mk_socket_reset(socket_fd);

        /* Check if reuse port can be enabled on this socket */
        if (reuse_port == MK_TRUE &&
            (server->kernel_features & MK_KERNEL_SO_REUSEPORT)) {
            ret = mk_socket_set_tcp_reuseport(socket_fd);
            if (ret == -1) {
                mk_warn("Could not use SO_REUSEPORT, using fair balancing mode");
                server->scheduler_mode = MK_SCHEDULER_FAIR_BALANCING;
            }
        }

        ret = mk_socket_bind(socket_fd, rp->ai_addr, rp->ai_addrlen,
                             MK_SOMAXCONN, server);
        if(ret == -1) {
            mk_err("Cannot listen on %s:%s", listen_addr, port);
            freeaddrinfo(res);
            return -1;
        }
        break;
    }
    freeaddrinfo(res);

    if (rp == NULL)
        return -1;

    return socket_fd;
}
예제 #2
0
파일: patas.c 프로젝트: f13mash/monkey
int mk_patas_validate_node(const char *host, int port)
{
    int i, j;
    char local_addr[16], node_addr[16];
    struct hostent local, *node;
    struct in_addr **node_addr_list, **local_addr_list;

    memcpy(&local, gethostbyname("localhost"), sizeof(struct hostent));
    node = gethostbyname(host);

    if (!node) {
        mk_warn("Could not determinate hostname");
        return -1;
    }

    local_addr_list = (struct in_addr **) local.h_addr_list;
    node_addr_list = (struct in_addr **) node->h_addr_list;

    for (i=0; local_addr_list[i] != NULL; i++) {
        inet_ntop(PF_INET, local.h_addr_list[i], local_addr, 16 );

        for (j=0; node_addr_list[j] != NULL; j++) {
            inet_ntop(PF_INET, node->h_addr_list[j], node_addr, 16);

            if (strcmp(local_addr, node_addr) == 0 && 
                mk_api->config->serverport == port) {
                mk_warn("Node %s:%i = localhost:%i, skip node\n", 
                        host, port, port);
                return -1;
            }
        }
    }

    return 0;
}
예제 #3
0
파일: mk_socket.c 프로젝트: tmrts/monkey
int mk_socket_ip_str(int socket_fd, char **buf, int size, unsigned long *len)
{
    int ret;
    struct sockaddr_storage addr;
    socklen_t s_len = sizeof(addr);

    ret = getpeername(socket_fd, (struct sockaddr *) &addr, &s_len);

    if (mk_unlikely(ret == -1)) {
        MK_TRACE("[FD %i] Can't get addr for this socket", socket_fd);
        return -1;
    }

    errno = 0;

    if(addr.ss_family == AF_INET) {
        if((inet_ntop(AF_INET, &((struct sockaddr_in *)&addr)->sin_addr,
                      *buf, size)) == NULL) {
            mk_warn("mk_socket_ip_str: Can't get the IP text form (%i)", errno);
            return -1;
        }
    }
    else if(addr.ss_family == AF_INET6) {
        if((inet_ntop(AF_INET6, &((struct sockaddr_in6 *)&addr)->sin6_addr,
                      *buf, size)) == NULL) {
            mk_warn("mk_socket_ip_str: Can't get the IP text form (%i)", errno);
            return -1;
        }
    }

    *len = strlen(*buf);
    return 0;
}
예제 #4
0
파일: liana.c 프로젝트: diadara/monkey
int _mkp_network_io_server(int port, char *listen_addr, int reuse_port)
{
    int socket_fd = -1;
    int ret;
    char *port_str = 0;
    unsigned long len;
    struct addrinfo hints;
    struct addrinfo *res, *rp;

    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags = AI_PASSIVE;

    mk_api->str_build(&port_str, &len, "%d", port);

    ret = getaddrinfo(listen_addr, port_str, &hints, &res);
    mk_api->mem_free(port_str);
    if(ret != 0) {
        mk_err("Can't get addr info: %s", gai_strerror(ret));
        return -1;
    }

    for(rp = res; rp != NULL; rp = rp->ai_next) {
        socket_fd = _mkp_network_io_create_socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);

        if( socket_fd == -1) {
            mk_warn("Error creating server socket, retrying");
            continue;
        }

        mk_api->socket_set_tcp_nodelay(socket_fd);
        mk_api->socket_reset(socket_fd);

        /* Check if reuse port can be enabled on this socket */
        if (reuse_port == MK_TRUE &&
            (mk_api->config->kernel_features & MK_KERNEL_SO_REUSEPORT)) {
            ret = mk_api->socket_set_tcp_reuseport(socket_fd);
            if (ret == -1) {
                mk_warn("Could not use SO_REUSEPORT, using fair balancing mode");
                mk_api->config->scheduler_mode = MK_SCHEDULER_FAIR_BALANCING;
            }
        }

        ret = _mkp_network_io_bind(socket_fd, rp->ai_addr, rp->ai_addrlen, MK_SOMAXCONN);
        if(ret == -1) {
            mk_err("Cannot listen on %s:%i\n", listen_addr, port);
            continue;
        }
        break;
    }
    freeaddrinfo(res);

    if (rp == NULL)
        return -1;

    return socket_fd;
}
예제 #5
0
/* Return the number of clients that can be attended  */
unsigned int mk_server_capacity()
{
    int ret;
    int cur;
    struct rlimit lim;

    /* Limit by system */
    getrlimit(RLIMIT_NOFILE, &lim);
    cur = lim.rlim_cur;

    if (mk_config->fd_limit > cur) {
        lim.rlim_cur = mk_config->fd_limit;
        lim.rlim_max = mk_config->fd_limit;

        ret = setrlimit(RLIMIT_NOFILE, &lim);
        if (ret == -1) {
            mk_warn("Could not increase FDLimit to %i.", mk_config->fd_limit);
        }
        else {
            cur = mk_config->fd_limit;
        }
    }
    else if (mk_config->fd_limit > 0) {
        cur = mk_config->fd_limit;
    }

    return cur;
}
예제 #6
0
파일: mk_utils.c 프로젝트: Doeme/monkey
/* Remove PID file */
int mk_utils_remove_pid(char *path)
{
    if (unlink(path)) {
        mk_warn("cannot delete pidfile\n");
    }
    return 0;
}
예제 #7
0
int mk_conn_read(int socket)
{
    int ret;
    struct client_session *cs;
    struct sched_list_node *sched;

    MK_TRACE("[FD %i] Connection Handler / read", socket);

    /* Plugin hook */
    ret = mk_plugin_event_read(socket);

    switch(ret) {
    case MK_PLUGIN_RET_EVENT_OWNED:
        return MK_PLUGIN_RET_CONTINUE;
    case MK_PLUGIN_RET_EVENT_CLOSE:
        return -1;
    case MK_PLUGIN_RET_EVENT_CONTINUE:
        break; /* just return controller to invoker */
    }

    sched = mk_sched_get_thread_conf();
    cs = mk_session_get(socket);
    if (!cs) {
        /* Note: Linux don't set TCP_NODELAY socket flag by default */
        if (mk_socket_set_tcp_nodelay(socket) != 0) {
            mk_warn("TCP_NODELAY failed");
        }

        /* Create session for the client */
        MK_TRACE("[FD %i] Create session", socket);
        cs = mk_session_create(socket, sched);
        if (!cs) {
            return -1;
        }
    }

    /* Read incomming data */
    ret = mk_handler_read(socket, cs);
    if (ret > 0) {
        if (mk_http_pending_request(cs) == 0) {
            mk_epoll_change_mode(sched->epoll_fd,
                                 socket, MK_EPOLL_WRITE, MK_EPOLL_LEVEL_TRIGGERED);
        }
        else if (cs->body_length + 1 >= config->max_request_size) {
            /*
             * Request is incomplete and our buffer is full,
             * close connection
             */
            mk_session_remove(socket);
            return -1;
        }
        else {
            MK_TRACE("[FD %i] waiting for pending data", socket);
        }
    }

    return ret;
}
예제 #8
0
파일: mk_socket.c 프로젝트: Doeme/monkey
int mk_socket_connect(char *host, int port, int async)
{
    int ret;
    int socket_fd = -1;
    char *port_str = 0;
    unsigned long len;
    struct addrinfo hints;
    struct addrinfo *res, *rp;

    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;

    mk_string_build(&port_str, &len, "%d", port);

    ret = getaddrinfo(host, port_str, &hints, &res);
    mk_mem_free(port_str);
    if(ret != 0) {
        mk_err("Can't get addr info: %s", gai_strerror(ret));
        return -1;
    }
    for (rp = res; rp != NULL; rp = rp->ai_next) {
        socket_fd = mk_socket_create(rp->ai_family,
                                     rp->ai_socktype, rp->ai_protocol);

        if (socket_fd == -1) {
            mk_warn("Error creating client socket, retrying");
            continue;
        }

        if (async == MK_TRUE) {
            mk_socket_set_nonblocking(socket_fd);
        }

        ret = connect(socket_fd,
                      (struct sockaddr *) rp->ai_addr, rp->ai_addrlen);
        if (ret == -1) {
            if (errno == EINPROGRESS) {
                break;
            }
            else {
                printf("%s", strerror(errno));
                perror("connect");
                exit(1);
                close(socket_fd);
                continue;
            }
        }
        break;
    }
    freeaddrinfo(res);

    if (rp == NULL)
        return -1;

    return socket_fd;
}
예제 #9
0
/* Remove PID file */
int mk_utils_remove_pid()
{
    mk_user_undo_uidgid();
    if (unlink(mk_config->pid_file_path)) {
        mk_warn("cannot delete pidfile\n");
    }
    mk_config->pid_status = MK_FALSE;
    return 0;
}
예제 #10
0
//duda_package_t *duda_package_load(const char *pkgname)
duda_package_t *duda_package_load(const char *pkgname, struct duda_api_objects *api)
{
    int ret;
    char *package = NULL;
    void *handle = NULL;
    unsigned long len;
    struct file_info finfo;
    duda_package_t *(*init_pkg)() = NULL;
    duda_package_t *package_info;

    mk_api->str_build(&package, &len, "%s/%s.dpkg", packages_root, pkgname);
    ret = mk_api->file_get_info(package, &finfo);

    if (ret != 0) {
        mk_err("Duda: Package '%s' not found", pkgname);
        mk_api->mem_free(package);
        exit(EXIT_FAILURE);
    }

    if (finfo.is_file == MK_FALSE) {
        mk_warn("Duda: Invalid Package '%s'", pkgname);
        mk_api->mem_free(package);
        return NULL;
    }

    handle = duda_load_library(package);
    if (!handle) {
        mk_warn("Duda: Invalid Package format '%s'", pkgname);
        mk_api->mem_free(package);
        return NULL;
    }

    init_pkg = duda_load_symbol(handle, "init_duda_package");
    if (!init_pkg) {
        mk_err("Duda: the package '%s' is broken", pkgname);
        exit(EXIT_FAILURE);
    }

    package_info = init_pkg(api);
    mk_api->mem_free(package);

    return package_info;
}
예제 #11
0
파일: liana.c 프로젝트: clbr/monkey
int _mkp_network_io_bind(int socket_fd, const struct sockaddr *addr, socklen_t addrlen, int backlog)
{
    int ret;

    ret = bind(socket_fd, addr, addrlen);

    if( ret == -1 ) {
        mk_warn("Error binding socket");
        return ret;
    }

    ret = listen(socket_fd, backlog);

    if(ret == -1 ) {
        mk_warn("Error setting up the listener");
        return -1;
    }

    return ret;
}
예제 #12
0
/*
 * Read the main configuration file for dirhtml: dirhtml.conf,
 * it will alloc the dirhtml_conf struct
*/
int mk_dirhtml_read_config(char *path)
{
    unsigned long len;
    char *default_file = NULL;
    struct mk_rconf *conf;
    struct mk_rconf_section *section;
    struct file_info finfo;

    mk_api->str_build(&default_file, &len, "%sdirhtml.conf", path);
    conf = mk_api->config_create(default_file);
    if (!conf) {
        return -1;
    }

    section = mk_api->config_section_get(conf, "DIRLISTING");
    if (!section) {
        mk_err("Could not find DIRLISTING tag in configuration file");
        exit(EXIT_FAILURE);
    }

    /* alloc dirhtml config struct */
    dirhtml_conf = mk_api->mem_alloc(sizeof(struct dirhtml_config));
    dirhtml_conf->theme = mk_api->config_section_get_key(section, "Theme",
                                                         MK_RCONF_STR);
    dirhtml_conf->theme_path = NULL;

    mk_api->str_build(&dirhtml_conf->theme_path, &len,
                      "%sthemes/%s/", path, dirhtml_conf->theme);
    mk_api->mem_free(default_file);

    if (mk_api->file_get_info(dirhtml_conf->theme_path,
                              &finfo, MK_FILE_READ) != 0) {
        mk_warn("Dirlisting: cannot load theme from '%s'", dirhtml_conf->theme_path);
        mk_warn("Dirlisting: unloading plugin");
        return -1;
    }

    mk_api->config_free(conf);
    return 0;
}
예제 #13
0
파일: mk_socket.c 프로젝트: neeraj9/monkey
int mk_socket_bind(int socket_fd, const struct sockaddr *addr,
                   socklen_t addrlen, int backlog)
{
    int ret;

    ret = bind(socket_fd, addr, addrlen);
    if( ret == -1 ) {
        mk_warn("Error binding socket");
        return ret;
    }

    /*
     * Enable TCP_FASTOPEN by default: if for some reason this call fail,
     * it will not affect the behavior of the server, in order to succeed,
     * Monkey must be running in a Linux system with Kernel >= 3.7 and the
     * tcp_fastopen flag enabled here:
     *
     *     # cat /proc/sys/net/ipv4/tcp_fastopen
     *
     * To enable this feature just do:
     *
     *     # echo 1 > /proc/sys/net/ipv4/tcp_fastopen
     */
    if (mk_config->kernel_features & MK_KERNEL_TCP_FASTOPEN) {
        ret = mk_socket_set_tcp_fastopen(socket_fd);
        if (ret == -1) {
            mk_warn("Could not set TCP_FASTOPEN");
        }
    }

    ret = listen(socket_fd, backlog);
    if(ret == -1 ) {
        mk_warn("Error setting up the listener");
        return -1;
    }

    return ret;
}
예제 #14
0
파일: mk_utils.c 프로젝트: diadara/monkey
/* Remove PID file */
int mk_utils_remove_pid()
{
    unsigned long len = 0;
    char *filepath = NULL;

    mk_string_build(&filepath, &len, "%s.%d", config->pid_file_path, config->serverport);
    mk_user_undo_uidgid();
    if (unlink(filepath)) {
        mk_warn("cannot delete pidfile\n");
    }
    mk_mem_free(filepath);
    config->pid_status = MK_FALSE;
    return 0;
}
예제 #15
0
파일: liana.c 프로젝트: clbr/monkey
int _mkp_network_io_server(int port, char *listen_addr)
{
    int socket_fd = -1;
    int ret;
    char *port_str = 0;
    unsigned long len;
    struct addrinfo hints;
    struct addrinfo *res, *rp;

    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags = AI_PASSIVE;

    mk_api->str_build(&port_str, &len, "%d", port);

    ret = getaddrinfo(listen_addr, port_str, &hints, &res);
    mk_api->mem_free(port_str);
    if(ret != 0) {
        mk_err("Can't get addr info: %s", gai_strerror(ret));
        return -1;
    }

    for(rp = res; rp != NULL; rp = rp->ai_next) {
        socket_fd = _mkp_network_io_create_socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);

        if( socket_fd == -1) {
            mk_warn("Error creating server socket, retrying");
            continue;
        }

        mk_api->socket_set_tcp_nodelay(socket_fd);
        mk_api->socket_reset(socket_fd);
        ret = _mkp_network_io_bind(socket_fd, rp->ai_addr, rp->ai_addrlen, MK_SOMAXCONN);

        if(ret == -1) {
            mk_err("Port %i cannot be used, retrying\n", port);
            continue;
        }
        break;
    }
    freeaddrinfo(res);

    if (rp == NULL)
        return -1;

    return socket_fd;
}
예제 #16
0
파일: liana.c 프로젝트: diadara/monkey
/* We need to know how to solve the problem with AF_INET and AF_INET6 */
int _mkp_network_io_connect(char *host, int port)
{
    int ret;
    int socket_fd = -1;
    char *port_str = 0;
    unsigned long len;
    struct addrinfo hints;
    struct addrinfo *res, *rp;

    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;

    mk_api->str_build(&port_str, &len, "%d", port);

    ret = getaddrinfo(host, port_str, &hints, &res);
    mk_api->mem_free(port_str);
    if(ret != 0) {
        mk_err("Can't get addr info: %s", gai_strerror(ret));
        return -1;
    }
    for(rp = res; rp != NULL; rp = rp->ai_next) {
        socket_fd = _mkp_network_io_create_socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);

        if( socket_fd == -1) {
            mk_warn("Error creating client socket, retrying");
            continue;
        }

        if (connect(socket_fd,
                    (struct sockaddr *) rp->ai_addr, rp->ai_addrlen) == -1) {
            close(socket_fd);
            mk_err("Can't connect to %s, retrying", host);
            continue;
        }

        break;
    }
    freeaddrinfo(res);

    if (rp == NULL)
        return -1;

    return socket_fd;
}
예제 #17
0
/* Remove PID file */
int mk_utils_remove_pid()
{
    unsigned long len = 0;
    char *filepath = NULL;
    struct mk_config_listener *listen;

    listen = mk_list_entry_first(&config->listeners,
                                 struct mk_config_listener, _head);
    mk_string_build(&filepath, &len, "%s.%s",
                    config->pid_file_path,
                    listen->port);
    mk_user_undo_uidgid();
    if (unlink(filepath)) {
        mk_warn("cannot delete pidfile\n");
    }
    mk_mem_free(filepath);
    config->pid_status = MK_FALSE;
    return 0;
}
예제 #18
0
파일: mk_user.c 프로젝트: AmesianX/monkey
/* Change process user */
int mk_user_set_uidgid()
{
    struct passwd *usr;

    /* Launched by root ? */
    if (geteuid() == 0 && config->user) {
        struct rlimit rl;

        if (getrlimit(RLIMIT_NOFILE, &rl)) {
            mk_warn("cannot get resource limits");
        }

        /* Check if user exists  */
        if ((usr = getpwnam(config->user)) == NULL) {
            mk_err("Invalid user '%s'", config->user);
            goto out;
        }

        if (initgroups(config->user, usr->pw_gid) != 0) {
            mk_err("Initgroups() failed");
        }

        /* Change process UID and GID */
        if (setegid(usr->pw_gid) == -1) {
            mk_err("I cannot change the GID to %u", usr->pw_gid);
        }

        if (seteuid(usr->pw_uid) == -1) {
            mk_err("I cannot change the UID to %u", usr->pw_uid);
        }

        config->is_seteuid = MK_TRUE;
    }

    out:

    /* Variables set for run checks on file permission */
    EUID = geteuid();
    EGID = getegid();

    return 0;
}
예제 #19
0
void mk_server_loop(int server_fd)
{
    int ret;
    int remote_fd;

    /* Activate TCP_DEFER_ACCEPT */
    if (mk_socket_set_tcp_defer_accept(server_fd) != 0) {
            mk_warn("TCP_DEFER_ACCEPT failed");
    }

    /* Rename worker */
    mk_utils_worker_rename("monkey: server");
    mk_info("HTTP Server started");

    while (1) {
        remote_fd = mk_socket_accept(server_fd);

        if (mk_unlikely(remote_fd == -1)) {
            continue;
        }

#ifdef TRACE
        MK_TRACE("New connection arrived: FD %i", remote_fd);

        int i;
        struct sched_list_node *node;

        node = sched_list;
        for (i=0; i < config->workers; i++) {
            MK_TRACE("Worker Status");
            MK_TRACE(" WID %i / conx = %llu", node[i].idx, node[i].accepted_connections - node[i].closed_connections);
        }
#endif

        /* Assign socket to worker thread */
        ret = mk_sched_add_client(remote_fd);
        if (ret == -1) {
            close(remote_fd);
        }
    }
}
예제 #20
0
파일: monkey.c 프로젝트: iamaeternus/monkey
/* MAIN */
int main(int argc, char **argv)
{
    int opt;
    char *port_override = NULL;
    int workers_override = -1;
    int run_daemon = 0;
    int balancing_mode = MK_FALSE;
    int allow_shared_sockets = MK_FALSE;
    char *one_shot = NULL;
    char *pid_file = NULL;
    char *transport_layer = NULL;
    char *path_config = NULL;
    char *server_conf_file = NULL;
    char *plugin_load_conf_file = NULL;
    char *sites_conf_dir = NULL;
    char *plugins_conf_dir = NULL;
    char *mimes_conf_file = NULL;

    static const struct option long_opts[] = {
        { "configdir",              required_argument,  NULL, 'c' },
        { "serverconf",             required_argument,  NULL, 's' },
        { "build",                  no_argument,        NULL, 'b' },
        { "daemon",                 no_argument,        NULL, 'D' },
        { "pid-file",               required_argument,  NULL, 'I' },
        { "port",                   required_argument,  NULL, 'p' },
        { "one-shot",               required_argument,  NULL, 'o' },
        { "transport",              required_argument,  NULL, 't' },
        { "workers",                required_argument,  NULL, 'w' },
        { "version",                no_argument,        NULL, 'v' },
        { "help",                   no_argument,        NULL, 'h' },
        { "mimes-conf-file",        required_argument,  NULL, 'm' },
        { "plugin-load-conf-file",  required_argument,  NULL, 'l' },
        { "plugins-conf-dir",       required_argument,  NULL, 'P' },
        { "sites-conf-dir",         required_argument,  NULL, 'S' },
        { "balancing-mode",         no_argument,        NULL, 'B' },
        { "allow-shared-sockets",   no_argument,        NULL, 'T' },
        { NULL, 0, NULL, 0 }
    };

    while ((opt = getopt_long(argc, argv, "bDI:Svhp:o:t:w:c:s:m:l:P:S:BT",
                              long_opts, NULL)) != -1) {
        switch (opt) {
        case 'b':
            mk_build_info();
            exit(EXIT_SUCCESS);
        case 'v':
            mk_version();
            exit(EXIT_SUCCESS);
        case 'h':
            mk_help(EXIT_SUCCESS);
        case 'D':
            run_daemon = 1;
            break;
        case 'I':
            pid_file = optarg;
            break;
        case 'p':
            port_override = optarg;
            break;
        case 'o':
            one_shot = optarg;
            break;
        case 't':
            transport_layer = mk_string_dup(optarg);
            break;
        case 'w':
            workers_override = atoi(optarg);
            break;
        case 'c':
            path_config = optarg;
            break;
        case 's':
            server_conf_file = optarg;
            break;
        case 'm':
            mimes_conf_file = optarg;
            break;
        case 'P':
            plugins_conf_dir = optarg;
            break;
        case 'S':
            sites_conf_dir = optarg;
            break;
        case 'B':
            balancing_mode = MK_TRUE;
            break;
        case 'T':
            allow_shared_sockets = MK_TRUE;
            break;
        case 'l':
            plugin_load_conf_file = optarg;
            break;
        case '?':
            mk_help(EXIT_FAILURE);
        }
    }

    /* setup basic configurations */
    mk_config = mk_config_init();

    /* Init Kernel version data */
    mk_kernel_init();
    mk_kernel_features();

    /* set configuration path */
    if (!path_config) {
        mk_config->path_config = MK_PATH_CONF;
    }
    else {
        mk_config->path_config = path_config;
    }

    /* set target configuration file for the server */
    if (!server_conf_file) {
        mk_config->server_conf_file = MK_DEFAULT_CONFIG_FILE;
    }
    else {
        mk_config->server_conf_file = server_conf_file;
    }

    if (!pid_file) {
        mk_config->pid_file_path = NULL;
    }
    else {
        mk_config->pid_file_path = pid_file;
    }

    if (run_daemon) {
        mk_config->is_daemon = MK_TRUE;
    }
    else {
        mk_config->is_daemon = MK_FALSE;
    }

    if (!mimes_conf_file) {
        mk_config->mimes_conf_file = MK_DEFAULT_MIMES_CONF_FILE;
    }
    else {
        mk_config->mimes_conf_file = mimes_conf_file;
    }

    if (!plugin_load_conf_file) {
        mk_config->plugin_load_conf_file = MK_DEFAULT_PLUGIN_LOAD_CONF_FILE;
    }
    else {
        mk_config->plugin_load_conf_file = plugin_load_conf_file;
    }

    if (!sites_conf_dir) {
        mk_config->sites_conf_dir = MK_DEFAULT_SITES_CONF_DIR;
    }
    else {
        mk_config->sites_conf_dir = sites_conf_dir;
    }

    if (!plugins_conf_dir) {
        mk_config->plugins_conf_dir = MK_DEFAULT_PLUGINS_CONF_DIR;
    }
    else {
        mk_config->plugins_conf_dir = plugins_conf_dir;
    }

    /* Override some configuration */
    mk_config->one_shot = one_shot;
    mk_config->port_override = port_override;
    mk_config->transport_layer = transport_layer;

#ifdef TRACE
    monkey_init_time = time(NULL);
    MK_TRACE("Monkey TRACE is enabled");
    env_trace_filter = getenv("MK_TRACE_FILTER");
    pthread_mutex_init(&mutex_trace, (pthread_mutexattr_t *) NULL);
#endif
    pthread_mutex_init(&mutex_port_init, (pthread_mutexattr_t *) NULL);

    mk_version();
    mk_signal_init();

#ifdef LINUX_TRACE
    mk_info("Linux Trace enabled");
#endif

    /* Override number of thread workers */
    if (workers_override >= 0) {
        mk_config->workers = workers_override;
    }
    else {
        mk_config->workers = -1;
    }

    /* Core and Scheduler setup */
    mk_config_start_configure();
    mk_sched_init();


    if (balancing_mode == MK_TRUE) {
        mk_config->scheduler_mode = MK_SCHEDULER_FAIR_BALANCING;
    }

    /* Clock init that must happen before starting threads */
    mk_clock_sequential_init();

    /* Load plugins */
    mk_plugin_api_init();
    mk_plugin_load_all();

    /* Running Monkey as daemon */
    if (mk_config->is_daemon == MK_TRUE) {
        mk_utils_set_daemon();
    }

    /* Register PID of Monkey */
    mk_utils_register_pid();

    /* Workers: logger and clock */
    mk_clock_tid = mk_utils_worker_spawn((void *) mk_clock_worker_init, NULL);

    /* Init thread keys */
    mk_thread_keys_init();

    /* Configuration sanity check */
    mk_config_sanity_check();

    if (mk_config->scheduler_mode == MK_SCHEDULER_REUSEPORT &&
        mk_config_listen_check_busy() == MK_TRUE &&
        allow_shared_sockets == MK_FALSE) {
        mk_warn("Some Listen interface is busy, re-try using -T. Aborting.");
        exit(EXIT_FAILURE);
    }

    /* Invoke Plugin PRCTX hooks */
    mk_plugin_core_process();

    /* Launch monkey http workers */
    MK_TLS_INIT();
    mk_server_launch_workers();

    /* Print server details */
    mk_details();

    /* Change process owner */
    mk_user_set_uidgid();

    /* Server loop, let's listen for incomming clients */
    mk_server_loop();

    mk_mem_free(mk_config);
    return 0;
}
예제 #21
0
파일: patas.c 프로젝트: f13mash/monkey
/* Read configuration parameters */
int mk_patas_conf(char *confdir)
{
    int res;
    int val_port;
    char *val_host;
    char *val_uri;
    unsigned long len;
    char *conf_path=NULL;

    struct mk_config_section *section;
    struct mk_config_entry *entry;
    struct mk_patas_node *node;

    /* Init nodes list */
    mk_patas_nodes_list = mk_api->mem_alloc(sizeof(struct mk_list));
    mk_list_init(mk_patas_nodes_list);

    /* Read configuration */
    mk_api->str_build(&conf_path, &len, "%s/patas.conf", confdir);
    conf = mk_api->config_create(conf_path);
    section = mk_api->config_section_get(conf, "NODE");

    while (section) { 
        entry = section->entry;
        val_host = NULL;
        val_port = -1;
        val_uri = NULL;

        /* Get section values */
        val_host = mk_api->config_section_getval(section, "IP", MK_CONFIG_VAL_STR);
        val_port = (int)  mk_api->config_section_getval(section, "Port", MK_CONFIG_VAL_NUM);
        val_uri  = mk_api->config_section_getval(section, "Uri", MK_CONFIG_VAL_LIST);

        if (val_host && val_uri && val_port > 0) {
            /* validate that node:ip is not pointing this server */
            if (mk_patas_validate_node(val_host, val_port) < 0) {
                break;
            }

            /* alloc node */
            node = mk_api->mem_alloc(sizeof(struct mk_patas_node));
            node->host = val_host;
            node->port = val_port;
                
            /* pre-socket stuff */
            node->sockaddr = mk_api->mem_alloc_z(sizeof(struct sockaddr_in));
            node->sockaddr->sin_family = AF_INET;

            res = inet_pton(AF_INET, node->host, 
                            (void *) (&(node->sockaddr->sin_addr.s_addr)));
            if (res < 0) {
                mk_warn("Can't set remote->sin_addr.s_addr");
                mk_api->mem_free(node->sockaddr);
                return -1;
            }
            else if (res == 0) {
                mk_err("Invalid IP address");
                mk_api->mem_free(node->sockaddr);
                return -1;
            }

            node->sockaddr->sin_port = htons(node->port);
                
            /* add node to list */
            PLUGIN_TRACE("Balance Node: %s:%i", val_host, val_port);

            mk_list_add(&node->_head, mk_patas_nodes_list);
            mk_patas_n_nodes++;
        }
        section = section->next;
    }

    mk_api->mem_free(conf_path);
    return 0;
}