Ejemplo n.º 1
0
/* 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;
}
Ejemplo n.º 2
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;
}