Exemplo n.º 1
0
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;
}
Exemplo n.º 2
0
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_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;
}
Exemplo n.º 4
0
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;
}
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;
}
Exemplo n.º 6
0
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;
}
Exemplo n.º 7
0
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_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;
}
Exemplo n.º 9
0
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;
}
Exemplo n.º 10
0
ret_t
cherokee_spawner_spawn (cherokee_buffer_t         *binary,
                        cherokee_buffer_t         *user,
                        uid_t                      uid,
                        gid_t                      gid,
                        int                        env_inherited,
                        char                     **envp,
                        cherokee_logger_writer_t  *error_writer,
                        pid_t                     *pid_ret)
{
#ifdef HAVE_SYSV_SEMAPHORES
    char             **n;
    int               *pid_shm;
    int                pid_prev;
    int                k;
    int                phase;
    int                envs     = 0;
    cherokee_buffer_t  tmp      = CHEROKEE_BUF_INIT;

#define ALIGN4(buf)						\
	while (buf.len & 0x3) {					\
		cherokee_buffer_add_char (&buf, '\0');		\
	}


    /* Check it's initialized
     */
    if ((! _active) ||
            (cherokee_spawn_shared.mem == NULL))
    {
        TRACE (ENTRIES, "Spawner is not active. Returning: %s\n", binary->buf);
        return ret_deny;
    }

    /* Lock the monitor mutex
     */
    k = CHEROKEE_MUTEX_TRY_LOCK (&spawning_mutex);
    if (k) {
        return ret_eagain;
    }

    /* Build the string
     * The first character of each block is a mark.
     */
    cherokee_buffer_ensure_size (&tmp, SPAWN_SHARED_LEN);

    /* 1.- Executable */
    phase = 0xF0;
    cherokee_buffer_add        (&tmp, (char *)&phase, sizeof(int));
    cherokee_buffer_add        (&tmp, (char *)&binary->len,   sizeof(int));
    cherokee_buffer_add_buffer (&tmp, binary);
    cherokee_buffer_add_char   (&tmp, '\0');
    ALIGN4 (tmp);

    /* 2.- UID & GID */
    phase = 0xF1;
    cherokee_buffer_add        (&tmp, (char *)&phase, sizeof(int));
    cherokee_buffer_add        (&tmp, (char *)&user->len, sizeof(int));
    cherokee_buffer_add_buffer (&tmp, user);
    cherokee_buffer_add_char   (&tmp, '\0');
    ALIGN4(tmp);

    cherokee_buffer_add (&tmp, (char *)&uid, sizeof(uid_t));
    cherokee_buffer_add (&tmp, (char *)&gid, sizeof(gid_t));

    /* 3.- Environment */
    phase = 0xF2;
    cherokee_buffer_add (&tmp, (char *)&phase, sizeof(int));

    for (n=envp; *n; n++) {
        envs ++;
    }

    cherokee_buffer_add (&tmp, (char *)&env_inherited, sizeof(int));
    cherokee_buffer_add (&tmp, (char *)&envs, sizeof(int));

    for (n=envp; *n; n++) {
        int len = strlen(*n);
        cherokee_buffer_add      (&tmp, (char *)&len, sizeof(int));
        cherokee_buffer_add      (&tmp, *n, len);
        cherokee_buffer_add_char (&tmp, '\0');
        ALIGN4(tmp);
    }

    /* 4.- Error log */
    phase = 0xF3;
    cherokee_buffer_add (&tmp, (char *)&phase, sizeof(int));

    write_logger (&tmp, error_writer);
    ALIGN4 (tmp);

    /* 5.- PID (will be rewritten by the other side) */
    phase = 0xF4;
    cherokee_buffer_add (&tmp, (char *)&phase, sizeof(int));

    pid_shm = (int *) (((char *)cherokee_spawn_shared.mem) + tmp.len);
    k        = *pid_ret;
    pid_prev = *pid_ret;
    cherokee_buffer_add (&tmp, (char *)&k, sizeof(int));

    /* Copy it to the shared memory
     */
    if (unlikely (tmp.len > SPAWN_SHARED_LEN)) {
        goto error;
    }

    memcpy (cherokee_spawn_shared.mem, tmp.buf, tmp.len);
    cherokee_buffer_mrproper (&tmp);

    /* Wake up the spawning thread
     */
    sem_unlock (cherokee_spawn_sem, SEM_LAUNCH_START);

    /* Wait for the PID
     */
    sem_adquire (cherokee_spawn_sem, SEM_LAUNCH_READY);

    if (*pid_shm == -1) {
        TRACE(ENTRIES, "Could not get the PID of: '%s'\n", binary->buf);
        goto error;
    }

    if (*pid_shm == pid_prev) {
        TRACE(ENTRIES, "Could not the new PID, previously it was %d\n", pid_prev);
        goto error;
    }

    TRACE(ENTRIES, "Successfully launched PID=%d\n", *pid_shm);
    *pid_ret = *pid_shm;

    CHEROKEE_MUTEX_UNLOCK (&spawning_mutex);
    return ret_ok;

error:
    CHEROKEE_MUTEX_UNLOCK (&spawning_mutex);
    return ret_error;
#else
    return ret_not_found;

#endif /* HAVE_SYSV_SEMAPHORES */
}
Exemplo n.º 11
0
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;
}
Exemplo n.º 12
0
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;
}
Exemplo n.º 13
0
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;
}
Exemplo n.º 14
0
ret_t
cherokee_logger_writer_release_buf (cherokee_logger_writer_t *writer)
{
	CHEROKEE_MUTEX_UNLOCK (&PRIV(writer)->mutex);
	return ret_ok;
}