/* * This function allow the core to invoke the closing connection process * when some connection was not proceesed due to a premature close or similar * exception, it also take care of invoke the STAGE_40 and STAGE_50 plugins events */ static void mk_request_premature_close(int http_status, struct mk_http_session *cs) { struct mk_http_request *sr; struct mk_list *sr_list = &cs->request_list; struct mk_list *host_list = &mk_config->hosts; /* * If the connection is too premature, we need to allocate a temporal session_request * to do not break the plugins stages */ if (mk_list_is_empty(sr_list) == 0) { sr = &cs->sr_fixed; memset(sr, 0, sizeof(struct mk_http_request)); mk_http_request_init(cs, sr); mk_list_add(&sr->_head, &cs->request_list); } else { sr = mk_list_entry_first(sr_list, struct mk_http_request, _head); } /* Raise error */ if (http_status > 0) { if (!sr->host_conf) { sr->host_conf = mk_list_entry_first(host_list, struct host, _head); } mk_http_error(http_status, cs, sr); /* STAGE_40, request has ended */ mk_plugin_stage_run_40(cs, sr); }
int mk_conn_read(int socket) { int ret; int status; struct mk_http_session *cs; struct mk_http_request *sr; 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_http_session_get(socket); if (!cs) { /* Check if is this a new connection for the Scheduler */ if (!mk_sched_get_connection(sched, socket)) { MK_TRACE("[FD %i] Registering new connection"); if (mk_sched_register_client(socket, sched) == -1) { MK_TRACE("[FD %i] Close requested", socket); return -1; } /* * New connections are not registered yet into the * events loop, we need to do it manually: */ mk_event_add(sched->loop, socket, MK_EVENT_READ, NULL); return 0; } /* Create session for the client */ MK_TRACE("[FD %i] Create session", socket); cs = mk_http_session_create(socket, sched); if (!cs) { return -1; } } /* Invoke the read handler, on this case we only support HTTP (for now :) */ ret = mk_http_handler_read(socket, cs); if (ret > 0) { if (mk_list_is_empty(&cs->request_list) == 0) { /* Add the first entry */ sr = &cs->sr_fixed; mk_list_add(&sr->_head, &cs->request_list); mk_http_request_init(cs, sr); } else { sr = mk_list_entry_first(&cs->request_list, struct mk_http_request, _head); } status = mk_http_parser(sr, &cs->parser, cs->body, cs->body_length); if (status == MK_HTTP_PARSER_OK) { MK_TRACE("[FD %i] HTTP_PARSER_OK", socket); mk_http_status_completed(cs); mk_event_add(sched->loop, socket, MK_EVENT_WRITE, NULL); } else if (status == MK_HTTP_PARSER_ERROR) { mk_http_session_remove(socket); MK_TRACE("[FD %i] HTTP_PARSER_ERROR", socket); return -1; } else { MK_TRACE("[FD %i] HTTP_PARSER_PENDING", socket); } } if (ret == -EAGAIN) { return 1; } return ret; }