ret_t cherokee_handler_zeromq_read_post (cherokee_handler_zeromq_t *hdl) { zmq_msg_t message; int re; ret_t ret; cherokee_buffer_t *post = &HANDLER_THREAD(hdl)->tmp_buf1; cherokee_buffer_t *out = &HANDLER_THREAD(hdl)->tmp_buf2; cherokee_connection_t *conn = HANDLER_CONN(hdl); /* Check for the post info */ if (! conn->post.has_info) { conn->error_code = http_bad_request; return ret_error; } cherokee_buffer_clean (post); ret = cherokee_post_read (&conn->post, &conn->socket, post); switch (ret) { case ret_ok: cherokee_connection_update_timeout (conn); break; case ret_eagain: ret = cherokee_thread_deactive_to_polling (HANDLER_THREAD(hdl), HANDLER_CONN(hdl), conn->socket.socket, FDPOLL_MODE_READ, false); if (ret != ret_ok) { return ret_error; } else { return ret_eagain; } default: conn->error_code = http_bad_request; return ret_error; } TRACE (ENTRIES, "Post contains: '%s'\n", post->buf); re = cherokee_post_read_finished (&conn->post); ret = re ? ret_ok : ret_eagain; if (hdl->encoder != NULL) { cherokee_buffer_clean(out); if (ret == ret_ok) { cherokee_encoder_flush(hdl->encoder, post, out); } else { cherokee_encoder_encode(hdl->encoder, post, out); } post = out; } cherokee_buffer_add_buffer(&hdl->output, post); if (ret == ret_ok) { cherokee_buffer_t *tmp = &HANDLER_THREAD(hdl)->tmp_buf1; cherokee_handler_zeromq_props_t *props = HANDLER_ZEROMQ_PROPS(hdl); zmq_msg_t envelope; zmq_msg_t message; cuint_t len; if ((cherokee_buffer_is_empty (&conn->web_directory)) || (cherokee_buffer_is_ending (&conn->web_directory, '/'))) { len = conn->web_directory.len; } else { len = conn->web_directory.len + 1; } cherokee_buffer_clean (tmp); cherokee_buffer_add (tmp, conn->request.buf + len, conn->request.len - len); TRACE(ENTRIES, "ZeroMQ: incomming path '%s'\n", tmp->buf); zmq_msg_init_size (&envelope, tmp->len); memcpy (zmq_msg_data (&envelope), tmp->buf, tmp->len); zmq_msg_init_size (&message, hdl->output.len); memcpy (zmq_msg_data (&message), hdl->output.buf, hdl->output.len); /* Atomic Section */ CHEROKEE_MUTEX_LOCK (&props->mutex); zmq_msg_send (&envelope, props->socket, ZMQ_DONTWAIT | ZMQ_SNDMORE); zmq_msg_send (&message, props->socket, ZMQ_DONTWAIT); CHEROKEE_MUTEX_UNLOCK (&props->mutex); zmq_msg_close (&envelope); zmq_msg_close (&message); } return ret; }
ret_t cherokee_handler_admin_read_post (cherokee_handler_admin_t *hdl) { int re; ret_t ret; char *tmp; cherokee_buffer_t post = CHEROKEE_BUF_INIT; cherokee_buffer_t line = CHEROKEE_BUF_INIT; cherokee_connection_t *conn = HANDLER_CONN(hdl); /* Check for the post info */ if (! conn->post.has_info) { conn->error_code = http_bad_request; return ret_error; } /* Process line per line */ ret = cherokee_post_read (&conn->post, &conn->socket, &post); switch (ret) { case ret_ok: case ret_eagain: break; default: conn->error_code = http_bad_request; return ret_error; } /* Parse */ TRACE (ENTRIES, "Post contains: '%s'\n", post.buf); cherokee_dwriter_list_open (&hdl->dwriter); for (tmp = post.buf;;) { char *end1 = strchr (tmp, CHR_LF); char *end2 = strchr (tmp, CHR_CR); char *end = cherokee_min_str (end1, end2); if (end == NULL) break; if (end - tmp < 2) break; /* Copy current line and go to the next one */ cherokee_buffer_add (&line, tmp, end - tmp); while ((*end == CHR_CR) || (*end == CHR_LF)) end++; tmp = end; /* Process current line */ ret = process_request_line (hdl, &line); if (ret == ret_error) { conn->error_code = http_bad_request; ret = ret_error; goto exit2; } /* Clean up for the next iteration */ cherokee_buffer_clean (&line); } cherokee_dwriter_list_close (&hdl->dwriter); /* There might be more POST to read */ re = cherokee_post_read_finished (&conn->post); ret = re ? ret_ok : ret_eagain; exit2: cherokee_buffer_mrproper (&post); cherokee_buffer_mrproper (&line); return ret; }
ret_t cherokee_post_send_to_fd (cherokee_post_t *post, cherokee_socket_t *sock_in, int fd_out, cherokee_buffer_t *tmp, cherokee_socket_status_t *blocking, cherokee_boolean_t *did_IO) { ret_t ret; int r; cherokee_buffer_t *buffer = tmp ? tmp : &post->send.buffer; switch (post->send.phase) { case cherokee_post_send_phase_read: TRACE (ENTRIES, "Post send, phase: %s\n", "read"); /* Read from the client */ ret = cherokee_post_read (post, sock_in, buffer); switch (ret) { case ret_ok: break; case ret_eagain: *blocking = socket_reading; return ret_eagain; default: return ret; } /* Did something, increase timeout */ *did_IO = true; /* Write it */ TRACE (ENTRIES, "Post buffer.len %d\n", buffer->len); post->send.phase = cherokee_post_send_phase_write; case cherokee_post_send_phase_write: TRACE (ENTRIES, "Post send, phase: write. Has %d bytes to send\n", buffer->len); if (! cherokee_buffer_is_empty (buffer)) { r = write (fd_out, buffer->buf, buffer->len); if (r < 0) { if (errno == EAGAIN) { *blocking = socket_writing; return ret_eagain; } TRACE(ENTRIES, "errno %d: %s\n", errno, strerror(errno)); return ret_error; } else if (r == 0) { return ret_eagain; } cherokee_buffer_move_to_begin (buffer, r); /* Did something, increase timeout */ *did_IO = true; } /* Next iteration */ if (! cherokee_buffer_is_empty (buffer)) { return ret_eagain; } if (! cherokee_post_read_finished (post)) { post->send.phase = cherokee_post_send_phase_read; return ret_eagain; } TRACE (ENTRIES, "Post send: %s\n", "finished"); cherokee_buffer_mrproper (&post->send.buffer); return ret_ok; default: SHOULDNT_HAPPEN; } return ret_error; }
ret_t cherokee_handler_tmi_read_post (cherokee_handler_tmi_t *hdl) { zmq_msg_t message; int re; ret_t ret; ret_t ret_final; cherokee_buffer_t *post = &HANDLER_THREAD(hdl)->tmp_buf1; cherokee_buffer_t *encoded = &HANDLER_THREAD(hdl)->tmp_buf2; cherokee_connection_t *conn = HANDLER_CONN(hdl); /* Check for the post info */ if (! conn->post.has_info) { conn->error_code = http_bad_request; return ret_error; } cherokee_buffer_clean (post); ret = cherokee_post_read (&conn->post, &conn->socket, post); switch (ret) { case ret_ok: cherokee_connection_update_timeout (conn); break; case ret_eagain: ret = cherokee_thread_deactive_to_polling (HANDLER_THREAD(hdl), HANDLER_CONN(hdl), conn->socket.socket, FDPOLL_MODE_READ, false); if (ret != ret_ok) { return ret_error; } else { return ret_eagain; } default: conn->error_code = http_bad_request; return ret_error; } TRACE (ENTRIES, "Post contains: '%s'\n", post->buf); re = cherokee_post_read_finished (&conn->post); ret_final = re ? ret_ok : ret_eagain; cherokee_buffer_clean(encoded); if (hdl->encoder != NULL) { if (ret == ret_ok) { cherokee_encoder_flush(hdl->encoder, post, encoded); } else { cherokee_encoder_encode(hdl->encoder, post, encoded); } } else { encoded = post; } cherokee_buffer_add_buffer(&hdl->output, post); if (ret_final == ret_ok) { cherokee_buffer_t *tmp = &HANDLER_THREAD(hdl)->tmp_buf1; cherokee_handler_tmi_props_t *props = HANDLER_TMI_PROPS(hdl); zmq_msg_t envelope; zmq_msg_t message; cuint_t len; if ((cherokee_buffer_is_empty (&conn->web_directory)) || (cherokee_buffer_is_ending (&conn->web_directory, '/'))) { len = conn->web_directory.len; } else { len = conn->web_directory.len + 1; } cherokee_buffer_clean (tmp); cherokee_buffer_add (tmp, conn->request.buf + len, conn->request.len - len); TRACE(ENTRIES, "ZeroMQ: incomming path '%s'\n", tmp->buf); zmq_msg_init_size (&envelope, tmp->len); memcpy (zmq_msg_data (&envelope), tmp->buf, tmp->len); zmq_msg_init_size (&message, hdl->output.len); memcpy (zmq_msg_data (&message), hdl->output.buf, hdl->output.len); /* Atomic Section */ CHEROKEE_MUTEX_LOCK (&props->mutex); zmq_msg_send (&envelope, props->socket, ZMQ_DONTWAIT | ZMQ_SNDMORE); zmq_msg_send (&message, props->socket, ZMQ_DONTWAIT); CHEROKEE_MUTEX_UNLOCK (&props->mutex); zmq_msg_close (&envelope); zmq_msg_close (&message); #ifdef LIBXML_PUSH_ENABLED if (hdl->validate_xml) { if (hdl->inflated) { hdl->strm.avail_in = hdl->output.len; hdl->strm.next_in = hdl->output.buf; /* run inflate() on input until output buffer not full */ do { #define CHUNK 131072 int have; char out[CHUNK]; hdl->strm.avail_out = CHUNK; hdl->strm.next_out = out; hdl->z_ret = inflate(&(hdl->strm), Z_NO_FLUSH); switch (hdl->z_ret) { case Z_NEED_DICT: hdl->z_ret = Z_DATA_ERROR; /* and fall through */ case Z_DATA_ERROR: case Z_MEM_ERROR: case Z_STREAM_ERROR: hdl->z_ret = Z_STREAM_ERROR; return ret_ok; } have = CHUNK - hdl->strm.avail_out; xmlParseChunk(hdl->ctxt, out, have, 0); } while (hdl->strm.avail_out == 0); } else { xmlParseChunk(hdl->ctxt, hdl->output.buf, hdl->output.len, 0); } } #endif } return ret_final; }
ret_t cherokee_post_send_to_socket (cherokee_post_t *post, cherokee_socket_t *sock_in, cherokee_socket_t *sock_out, cherokee_buffer_t *tmp, cherokee_socket_status_t *blocking, cherokee_boolean_t *did_IO) { ret_t ret; cherokee_buffer_t *buffer = tmp ? tmp : &post->send.buffer; switch (post->send.phase) { case cherokee_post_send_phase_read: TRACE (ENTRIES, "Post send, phase: %s\n", "read"); /* Read from the client */ ret = cherokee_post_read (post, sock_in, buffer); switch (ret) { case ret_ok: break; case ret_eagain: *blocking = socket_reading; return ret_eagain; default: return ret; } /* Did something, increase timeout */ *did_IO = true; /* Write it */ TRACE (ENTRIES, "Post buffer.len %d\n", buffer->len); post->send.phase = cherokee_post_send_phase_write; case cherokee_post_send_phase_write: TRACE (ENTRIES, "Post send, phase: write. Buffered: %d bytes\n", buffer->len); if (! cherokee_buffer_is_empty (buffer)) { ret = do_send_socket (sock_out, buffer, blocking); switch (ret) { case ret_ok: break; case ret_eagain: return ret_eagain; case ret_eof: case ret_error: return ret_error; default: RET_UNKNOWN(ret); return ret_error; } /* Did something, increase timeout */ *did_IO = true; } if (! cherokee_buffer_is_empty (buffer)) { return ret_eagain; } if (! cherokee_post_read_finished (post)) { post->send.phase = cherokee_post_send_phase_read; return ret_eagain; } TRACE (ENTRIES, "Post send: %s\n", "finished"); cherokee_buffer_mrproper (&post->send.buffer); return ret_ok; default: SHOULDNT_HAPPEN; } return ret_error; }