Exemplo n.º 1
0
static ret_t
connect_to (cherokee_downloader_t *downloader,
            cherokee_buffer_t     *host,
            cuint_t                port,
            int                    protocol)
{
	ret_t              ret;
	cherokee_socket_t *sock = &downloader->socket;

	TRACE(ENTRIES, "host=%s port=%d proto=%d\n", host->buf, port, protocol);

	/* Create the socket
	 */
	ret = cherokee_socket_create_fd (sock, AF_INET);
	if (unlikely(ret != ret_ok)) return ret_error;

	/* Set the port
	 */
	SOCKET_SIN_PORT(sock) = htons(port);

	/* Supposing it's an IP: convert it.
	 */
	ret = cherokee_socket_pton (sock, host);
	if (ret != ret_ok) {

		/* Oops! It might be a hostname. Try to resolve it.
		 */
		ret = cherokee_socket_gethostbyname (sock, host);
		if (unlikely(ret != ret_ok)) return ret_error;
	}

	/* Connect to server
	 */
	ret = cherokee_socket_connect (sock);
	TRACE(ENTRIES, "socket=%p ret=%d\n", sock, ret);

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

	/* Is this connection TLS?
	 */
	if ((protocol == https) &&
	    (sock->cryptor != NULL))
	{
		ret = cherokee_socket_init_client_tls (sock, host);
		if (ret != ret_ok)
			return ret;
	}

	TRACE(ENTRIES, "Exits ok; socket=%p\n", sock);
	return ret_ok;
}
Exemplo n.º 2
0
static ret_t
find_empty_port (int starting, int *port)
{
	ret_t             ret;
	cherokee_socket_t s;
	int               p     = starting;
	cherokee_buffer_t bind_ = CHEROKEE_BUF_INIT;

	cherokee_buffer_add_str (&bind_, "127.0.0.1");
	cherokee_socket_init (&s);

	while (true) {
		cherokee_socket_create_fd (&s, AF_INET);
		ret = cherokee_socket_bind (&s, p, &bind_);
		cherokee_socket_close (&s);

		if (ret == ret_ok)
			break;

		p += 1;
		if (unlikely (p > 0xFFFF)) {
			goto error;
		}
	}

	cherokee_socket_mrproper (&s);
	cherokee_buffer_mrproper (&bind_);

	*port = p;
	return ret_ok;

error:
	cherokee_socket_close (&s);
	cherokee_socket_mrproper (&s);
	cherokee_buffer_mrproper (&bind_);
	return ret_error;
}
Exemplo n.º 3
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);
}