Beispiel #1
0
ret_t
cherokee_buffer_read_file (cherokee_buffer_t *buf, char *filename)
{
	int r, f;
	ret_t ret;
	struct stat info;

	/* Stat() the file
	 */
	r = cherokee_stat (filename, &info);
	if (r != 0)
		return ret_error;

	/* Is a regular file?
	 */
	if (S_ISREG(info.st_mode) == 0)
		return ret_error;

	/* Maybe get memory
	 */
	ret = cherokee_buffer_ensure_size (buf, buf->len + info.st_size + 1);
	if (unlikely (ret != ret_ok))
		return ret;

	/* Open the file
	 */
	f = cherokee_open (filename, O_RDONLY | O_BINARY, 0);
	if (f < 0) {
		LOG_ERRNO(errno, cherokee_err_error, CHEROKEE_ERROR_BUFFER_OPEN_FILE, filename);
		return ret_error;
	}

	cherokee_fd_set_closexec (f);

	/* Read the content
	 */
	r = read (f, buf->buf + buf->len, info.st_size);
	if (r < 0) {
		buf->buf[buf->len] = '\0';

		cherokee_fd_close(f);
		return ret_error;
	}

	/* Close it and exit
	 */
	cherokee_fd_close(f);

	buf->len += r;
	buf->buf[buf->len] = '\0';

	return ret_ok;
}
Beispiel #2
0
ret_t
cherokee_socket_accept_fd (cherokee_socket_t   *server_socket,
                           int                 *new_fd,
                           cherokee_sockaddr_t *sa)
{
	ret_t     ret;
	socklen_t len;
	int       new_socket;

	/* Get the new connection
	 */
	len = sizeof (cherokee_sockaddr_t);

	do {
		new_socket = accept (server_socket->socket, &sa->sa, &len);
	} while ((new_socket == -1) && (errno == EINTR));

	if (new_socket < 0) {
		return ret_error;
	}

	/* It'd nice to be able to reuse the address even if the
	 * socket is still in TIME_WAIT statue (2*RTT ~ 120 seg)
	 */
	cherokee_fd_set_reuseaddr (new_socket);

	/* Close-on-exec: Child processes won't inherit this fd
	 */
	cherokee_fd_set_closexec (new_socket);

	/* Enables nonblocking I/O.
	 */
	ret = cherokee_fd_set_nonblocking (new_socket, true);
	if (ret != ret_ok) {
		LOG_WARNING (CHEROKEE_ERROR_SOCKET_NON_BLOCKING, new_socket);
		cherokee_fd_close (new_socket);
		return ret_error;
	}

	/* Disable Nagle's algorithm for this connection
	 * so that there is no delay involved when sending data
	 * which don't fill up a full IP datagram.
	 */
	ret = cherokee_fd_set_nodelay (new_socket, true);
	if (ret != ret_ok) {
		LOG_WARNING_S (CHEROKEE_ERROR_SOCKET_RM_NAGLES);
		cherokee_fd_close (new_socket);
		return ret_error;
	}

	*new_fd = new_socket;
	return ret_ok;
}
Beispiel #3
0
ret_t
cherokee_logger_writer_open (cherokee_logger_writer_t *writer)
{
	ret_t ret;

	switch (writer->type) {
	case cherokee_logger_writer_syslog:
		/* Nothing to do, syslog already opened at startup.
		 */
		goto out;

	case cherokee_logger_writer_pipe:
		ret = launch_logger_process (writer);
		if (ret != ret_ok)
			goto error;

		goto out;

	case cherokee_logger_writer_stderr:
		writer->fd = STDERR_FILENO;
		goto out;

	case cherokee_logger_writer_file:
		writer->fd = cherokee_open (writer->filename.buf, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE | O_NOFOLLOW, 0640);
		if (writer->fd == -1) {
			LOG_ERROR (CHEROKEE_ERROR_LOGGER_WRITER_APPEND, writer->filename.buf);
			ret = ret_error;
			goto error;
		}

		ret = cherokee_fd_set_closexec (writer->fd);
		if (ret != ret_ok)
			goto error;

		goto out;

	default:
		SHOULDNT_HAPPEN;
		ret = ret_error;
		goto error;
	}

out:
	writer->initialized = true;
	return ret_ok;
error:
	return ret;
}
ret_t
cherokee_proxy_util_init_socket (cherokee_socket_t *socket,
				 cherokee_source_t *src)
{
	ret_t                    ret;
	cherokee_resolv_cache_t *resolv;

	TRACE (ENTRIES, "Initializing proxy socket: %s\n",
	       cherokee_string_is_ipv6 (&src->host) ? "IPv6": "IPv4");

	/* Family */
	if (cherokee_string_is_ipv6 (&src->host)) {
		ret = cherokee_socket_set_client (socket, AF_INET6);
	} else {
		ret = cherokee_socket_set_client (socket, AF_INET);
	}

        if (unlikely(ret != ret_ok))
		return ret_error;

	/* TCP port */
        SOCKET_SIN_PORT(socket) = htons (src->port);

        /* IP host */
	ret = cherokee_resolv_cache_get_default (&resolv);
	if (unlikely (ret != ret_ok)) {
		return ret_error;
	}

	ret = cherokee_resolv_cache_get_host (resolv, &src->host, socket);
	if (ret != ret_ok) {
		return ret_error;
	}

	/* Set a few properties */
	cherokee_fd_set_closexec    (socket->socket);
	cherokee_fd_set_nonblocking (socket->socket, true);
	cherokee_fd_set_nodelay     (socket->socket, true);

	return ret_ok;
}
Beispiel #5
0
ret_t
cherokee_source_connect (cherokee_source_t *src, cherokee_socket_t *sock)
{
	ret_t                    ret;
	cherokee_resolv_cache_t *resolv;

	/* Short path: it's already connecting
	 */
	if (sock->socket >= 0) {
		return cherokee_socket_connect (sock);
	}

	/* Create the new socket and set the target IP info
	 */
	if (! cherokee_buffer_is_empty (&src->unix_socket)) {

		/* Create the socket descriptor
		 */
		ret = cherokee_socket_create_fd (sock, AF_UNIX);
		if (unlikely (ret != ret_ok)) {
			return ret;
		}

		ret = cherokee_socket_gethostbyname (sock, &src->unix_socket);
		if (unlikely (ret != ret_ok)) {
			return ret;
		}
	} else {
		cherokee_boolean_t     tested_all;
		const struct addrinfo *addr;
		const struct addrinfo *addr_info = NULL;

		/* Query the resolv cache
		 */
		ret = cherokee_resolv_cache_get_default (&resolv);
		if (unlikely (ret!=ret_ok)) {
			return ret;
		}

		ret = cherokee_resolv_cache_get_addrinfo (resolv, &src->host, &addr_info);
		if ((ret != ret_ok) || (addr_info == NULL)) {
			return ret_error;
		}

		/* Current address
		 */
		if (src->addr_current) {
			tested_all = false;
			addr = src->addr_current;
		} else {
			tested_all = true;
			addr = addr_info;
		}

		/* Create the fd for the address family
		 *
		 * Iterates through the different addresses of the
		 * host and stores a pointer to the first one with
		 * a supported family.
		 */
		while (addr != NULL) {
			ret = cherokee_socket_create_fd (sock, addr->ai_family);

#ifdef TRACE_ENABLED
			if (cherokee_trace_is_tracing()) {
				ret_t ret2;
				char ip[46];

				ret2 = cherokee_ntop (addr->ai_family, addr->ai_addr, ip, sizeof(ip));
				if (ret2 == ret_ok) {
					TRACE (ENTRIES, "Connecting to %s, ret=%d\n", ip, ret);
				}
			}
#endif

			if (ret == ret_ok) {
				src->addr_current = addr;
				break;
			}

			addr = addr->ai_next;
			if (addr == NULL) {
				if (tested_all) {
					return ret_error;
				}

				tested_all = true;
				src->addr_current = NULL;
				addr = addr_info;
				continue;
			}

			cherokee_socket_close(sock);
		}

		/* Update the new socket with the address info
		 */
		switch (src->addr_current->ai_family) {
		case AF_INET:
			SOCKET_ADDR_IPv4(sock)->sin_port = htons(src->port);
			break;
		case AF_INET6:
			SOCKET_ADDR_IPv6(sock)->sin6_port = htons(src->port);
			break;
		default:
			SHOULDNT_HAPPEN;
			return ret_error;
		}

		ret = cherokee_socket_update_from_addrinfo (sock, src->addr_current, 0);
		if (unlikely (ret != ret_ok)) {
			return ret_error;
		}
	}

	/* Set non-blocking */
	ret = cherokee_fd_set_nonblocking (sock->socket, true);
	if (unlikely (ret != ret_ok)) {
		LOG_ERRNO (errno, cherokee_err_error, CHEROKEE_ERROR_SOURCE_NONBLOCK, sock->socket);
	}

	/* Set close-on-exec and reuse-address */
	cherokee_fd_set_closexec  (sock->socket);
	cherokee_fd_set_reuseaddr (sock->socket);

	return cherokee_socket_connect (sock);
}
Beispiel #6
0
ret_t
cherokee_socket_accept_fd (cherokee_socket_t   *server_socket,
			   int                 *new_fd,
			   cherokee_sockaddr_t *sa)
{
	ret_t     ret;
	socklen_t len;
	int       new_socket;

	/* Get the new connection
	 */
	len = sizeof (cherokee_sockaddr_t);

	do {
		new_socket = accept (server_socket->socket, &sa->sa, &len);
	} while ((new_socket == -1) && (errno == EINTR));

	if (new_socket < 0) {
		return ret_error;
	}

#if 0 /* DISABLED */

	/* Deal with the FIN_WAIT2 state
	 */
	re = 1;
	re = setsockopt (new_socket, SOL_SOCKET, SO_KEEPALIVE, &re, sizeof(re));
	if (re == -1) {
		LOG_ERRNO (errno, cherokee_err_warning,
			   CHEROKEE_ERROR_SOCKET_SET_KEEPALIVE, new_socket);
	}

	linger.l_onoff  = 1;
	linger.l_linger = SECONDS_TO_LINGER;

	re = setsockopt (new_socket, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger));
	if (re == -1) {
		LOG_ERRNO (errno, cherokee_err_warning,
			   CHEROKEE_ERROR_SOCKET_SET_LINGER, new_socket);
	}
#endif

	/* Close-on-exec: Child processes won't inherit this fd
	 */
	cherokee_fd_set_closexec (new_socket);

	/* Enables nonblocking I/O.
	 */
	ret = cherokee_fd_set_nonblocking (new_socket, true);
	if (ret != ret_ok) {
		LOG_WARNING (CHEROKEE_ERROR_SOCKET_NON_BLOCKING, new_socket);

		cherokee_fd_close (new_socket);
		return ret_error;
	}

	/* Disable Nagle's algorithm for this connection
	 * so that there is no delay involved when sending data
	 * which don't fill up a full IP datagram.
	 */
	ret = cherokee_fd_set_nodelay (new_socket, true);
	if (ret != ret_ok) {
		LOG_WARNING_S (CHEROKEE_ERROR_SOCKET_RM_NAGLES);

		cherokee_fd_close (new_socket);
		return ret_error;
	}

	*new_fd = new_socket;
	return ret_ok;
}