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; }
/* * Check if the client request still has pending data. * * Return 0 when all parts of the expected data has arrived or -1 when * the connection is on a pending status due to HTTP spec. * * This function is called from request.c :: mk_handler_read(..) */ int mk_http_pending_request(struct client_session *cs) { int n; // ret; char *end; struct unparsed_method req; struct parsed_method rsp; if (cs->body_length >= mk_endblock.len) { end = (cs->body + cs->body_length) - mk_endblock.len; } else { return -1; } /* try to match CRLF at the end of the request */ if (cs->body_pos_end < 0) { if (strncmp(end, mk_endblock.data, mk_endblock.len) == 0) { cs->body_pos_end = cs->body_length - mk_endblock.len; } else if ((n = mk_string_search(cs->body, mk_endblock.data, MK_STR_SENSITIVE)) >= 0 ){ cs->body_pos_end = n; } else { return -1; } } memset(&req, 0, sizeof req); if (cs->first_method == MK_HTTP_METHOD_UNKNOWN) { /* Prepare message to send to the parser */ req.flag = 1; strncpy(req.req_buf, cs->body, cs->body_length); /* Send the actual message to the parser */ //ret = write(pfd_w, &req, sizeof(req.flag) + cs->body_length); //if(ret <= 0){ // fprintf(stderr, "Monkey: Write to pipe failed in pre-parsing mode\n"); //} /* Monkey reads parsed request struct from parser */ //memset(&rsp, 0, sizeof rsp); //ret = read(pfd_r, &rsp, sizeof rsp); //if(ret <= 0){ // fprintf(stderr, "Monkey: Read from pipe failed in pre-parsing mode\n"); //} /* process parsed method */ cs->first_method = rsp.first_method; } if (cs->first_method == MK_HTTP_METHOD_POST || cs->first_method == MK_HTTP_METHOD_PUT) { if (cs->body_pos_end > 0) { int content_length; int current; if (req.flag != 1) { /* send the request to the parser */ req.flag = 1; strncpy(req.req_buf, cs->body, cs->body_length); //ret = write(pfd_w, &req, sizeof(req.flag) + cs->body_length); //if(ret <= 0){ // fprintf(stderr, "Monkey: Write to pipe failed in pre-parsing mode\n"); //} /* Monkey reads parsed request struct from parser */ //memset(&rsp, 0, sizeof rsp); //ret = read(pfd_r, &rsp, sizeof rsp); //if(ret <= 0){ // fprintf(stderr, "Monkey: Read from pipe failed in pre-parsing mode\n"); //} } /* process reply from parser */ content_length = rsp.content_length; current = cs->body_length - cs->body_pos_end - mk_endblock.len; MK_TRACE("HTTP DATA %i/%i", current, content_length); if (content_length >= config->max_request_size) { return 0; } /* if first block has ended, we need to verify if exists * a previous block end, that will means that the POST * method has sent the whole information. * just for ref: pipelining is not allowed with POST */ if ((unsigned int) cs->body_pos_end == cs->body_length - mk_endblock.len) { /* Content-length is required, if is it not found, * we pass as successful in order to raise the error * later */ if (content_length <= 0) { mk_http_status_completed(cs); return 0; } else { return -1; } } else { if (current < content_length) { return -1; } else { mk_http_status_completed(cs); return 0; } } } else { return -1; } } mk_http_status_completed(cs); return 0; }