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