ret_t cherokee_logger_write_access (cherokee_logger_t *logger, void *conn) { ret_t ret; /* Sanity check */ if (unlikely (logger->write_access == NULL)) { return ret_error; } /* Deal with X-Real-IP */ if (logger->priv->x_real_ip.enabled) { ret = parse_x_real_ip (logger, CONN(conn)); if (unlikely (ret == ret_error)) { return ret_error; } } /* Call the virtual method */ CHEROKEE_MUTEX_LOCK (&PRIV(logger)->mutex); ret = logger->write_access (logger, conn); CHEROKEE_MUTEX_UNLOCK (&PRIV(logger)->mutex); return ret; }
ret_t cherokee_logger_writer_reopen (cherokee_logger_writer_t *writer) { ret_t ret; CHEROKEE_MUTEX_LOCK (&PRIV(writer)->mutex); switch (writer->type) { case cherokee_logger_writer_syslog: goto out; case cherokee_logger_writer_file: case cherokee_logger_writer_pipe: case cherokee_logger_writer_stderr: ret = logger_writer_close_file (writer); break; default: SHOULDNT_HAPPEN; goto error; } ret = cherokee_logger_writer_open (writer); if (ret != ret_ok) goto error; out: CHEROKEE_MUTEX_UNLOCK (&PRIV(writer)->mutex); return ret_ok; error: CHEROKEE_MUTEX_UNLOCK (&PRIV(writer)->mutex); return ret_error; }
ret_t cherokee_logger_writer_get_buf (cherokee_logger_writer_t *writer, cherokee_buffer_t **buf) { CHEROKEE_MUTEX_LOCK (&PRIV(writer)->mutex); *buf = &writer->buffer; return ret_ok; }
ret_t cherokee_handler_proxy_hosts_get (cherokee_handler_proxy_hosts_t *hosts, cherokee_source_t *src, cherokee_handler_proxy_poll_t **poll, cuint_t reuse_max) { ret_t ret; CHEROKEE_MUTEX_LOCK (&hosts->hosts_mutex); /* Build the index name */ cherokee_buffer_clean (&hosts->tmp); cherokee_buffer_add_buffer (&hosts->tmp, &src->host); cherokee_buffer_add_char (&hosts->tmp, ':'); cherokee_buffer_add_ulong10 (&hosts->tmp, src->port); /* Check the hosts tree */ ret = cherokee_avl_get (&hosts->hosts, &hosts->tmp, (void **)poll); switch (ret) { case ret_ok: break; case ret_not_found: { cherokee_handler_proxy_poll_t *n; ret = cherokee_handler_proxy_poll_new (&n, reuse_max); if (ret != ret_ok) return ret; cherokee_avl_add (&hosts->hosts, &hosts->tmp, n); *poll = n; break; } default: goto error; } /* Got it */ CHEROKEE_MUTEX_UNLOCK (&hosts->hosts_mutex); return ret_ok; error: CHEROKEE_MUTEX_LOCK (&hosts->hosts_mutex); return ret_error; }
ret_t cherokee_handler_proxy_conn_release (cherokee_handler_proxy_conn_t *pconn) { ret_t ret; cherokee_handler_proxy_poll_t *poll = pconn->poll_ref; CHEROKEE_MUTEX_LOCK (&poll->mutex); ret = poll_release (poll, pconn); CHEROKEE_MUTEX_UNLOCK (&poll->mutex); return ret; }
ret_t cherokee_logger_reopen (cherokee_logger_t *logger) { ret_t ret = ret_error; if (logger->reopen != NULL) { CHEROKEE_MUTEX_LOCK (&PRIV(logger)->mutex); ret = logger->reopen (logger); CHEROKEE_MUTEX_UNLOCK (&PRIV(logger)->mutex); } return ret; }
ret_t cherokee_handler_proxy_poll_get (cherokee_handler_proxy_poll_t *poll, cherokee_handler_proxy_conn_t **pconn, cherokee_source_t *src) { ret_t ret; cherokee_list_t *i; CHEROKEE_MUTEX_LOCK (&poll->mutex); if (poll->reuse_len > 0) { /* Reuse a prev connection */ poll->reuse_len -= 1; i = poll->reuse.prev; cherokee_list_del (i); cherokee_list_add (i, &poll->active); *pconn = PROXY_CONN(i); } else { cherokee_handler_proxy_conn_t *n; /* Create a new connection */ ret = cherokee_handler_proxy_conn_new (&n); if (ret != ret_ok) goto error; ret = cherokee_proxy_util_init_socket (&n->socket, src); if (ret != ret_ok) { cherokee_handler_proxy_conn_free (n); goto error; } cherokee_list_add (&n->listed, &poll->active); n->poll_ref = poll; *pconn = n; } CHEROKEE_MUTEX_UNLOCK (&poll->mutex); return ret_ok; error: CHEROKEE_MUTEX_UNLOCK (&poll->mutex); return ret_error; }
ret_t cherokee_logger_flush (cherokee_logger_t *logger) { ret_t ret = ret_error; /* If the logger is on backup mode, it shouldn't write anything * to the disk. Maintenance tasks have been taking place. */ if (logger->priv->backup_mode) { return ret_ok; } if (logger->flush) { CHEROKEE_MUTEX_LOCK (&PRIV(logger)->mutex); ret = logger->flush(logger); CHEROKEE_MUTEX_UNLOCK (&PRIV(logger)->mutex); } return ret; }
static void * get_sym_from_dlopen_handler (void *dl_handle, const char *sym) { void *re; const char *error; /* Clear the possible error and look for the symbol */ CHEROKEE_MUTEX_LOCK (&dlerror_mutex); dlerror(); re = (void *) dlsym(dl_handle, sym); if ((error = dlerror()) != NULL) { LOG_ERROR (CHEROKEE_ERROR_PLUGIN_LOAD_NO_SYM, sym, error); CHEROKEE_MUTEX_UNLOCK (&dlerror_mutex); return NULL; } CHEROKEE_MUTEX_UNLOCK (&dlerror_mutex); return re; }
static ret_t dylib_open (cherokee_plugin_loader_t *loader, const char *libname, int extra_flags, void **handler_out) { ret_t ret; void *lib; int flags; cherokee_buffer_t tmp = CHEROKEE_BUF_INIT; flags = RTLD_BASE | extra_flags; /* Build the path string */ ret = cherokee_buffer_add_va (&tmp, "%s/libplugin_%s." MOD_SUFFIX, loader->module_dir.buf, libname); if (unlikely(ret < ret_ok)) { cherokee_buffer_mrproper (&tmp); return ret; } /* Open the library */ CHEROKEE_MUTEX_LOCK (&dlerror_mutex); lib = dlopen (tmp.buf, flags); if (lib == NULL) { LOG_ERROR (CHEROKEE_ERROR_PLUGIN_DLOPEN, dlerror(), tmp.buf); CHEROKEE_MUTEX_UNLOCK (&dlerror_mutex); cherokee_buffer_mrproper (&tmp); return ret_error; } CHEROKEE_MUTEX_UNLOCK (&dlerror_mutex); /* Free the memory */ cherokee_buffer_mrproper (&tmp); *handler_out = lib; return ret_ok; }
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_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_logger_writer_flush (cherokee_logger_writer_t *writer, cherokee_boolean_t locked) { int re; ret_t ret = ret_ok; /* The internal buffer might be empty */ if (cherokee_buffer_is_empty (&writer->buffer)) { return ret_ok; } if (!locked) { CHEROKEE_MUTEX_LOCK (&PRIV(writer)->mutex); } /* If not, do the proper thing */ switch (writer->type) { case cherokee_logger_writer_stderr: /* In this case we ignore errors. */ re = fwrite (writer->buffer.buf, 1, writer->buffer.len, stderr); if (re != (size_t) writer->buffer.len) { ret = ret_error; } /* Cleanup the log buffer even if there is an error, * because it's safer to go on anyway. */ cherokee_buffer_clean (&writer->buffer); break; case cherokee_logger_writer_pipe: case cherokee_logger_writer_file: { ssize_t nwr = 0; size_t buflen = writer->buffer.len; /* If there is at least 1 page to write then round * down the length to speed up write(s). */ if (buflen > LOGGER_BUF_PAGESIZE) { buflen &= ~LOGGER_BUF_PAGESIZE; } do { nwr = write (writer->fd, writer->buffer.buf, buflen); } while (nwr == -1 && errno == EINTR); if (nwr <= 0) { /* If an error occured in blocking write, then * cleanup the log buffer now because we don't * want to let it grow too much. */ cherokee_buffer_clean (&writer->buffer); ret = ret_error; goto out; } /* OK, something has been written. */ cherokee_buffer_move_to_begin (&writer->buffer, nwr); if (! cherokee_buffer_is_empty (&writer->buffer)) { ret = ret_eagain; } break; } case cherokee_logger_writer_syslog: /* Write to syslog the whole log buffer, then cleanup * it in any case. */ ret = cherokee_syslog (LOG_INFO, &writer->buffer); cherokee_buffer_clean (&writer->buffer); break; default: SHOULDNT_HAPPEN; ret = ret_error; } out: if (! locked) { CHEROKEE_MUTEX_UNLOCK (&PRIV(writer)->mutex); } return ret; }