void connect(TreeLinkNode *root) {
     if(root == NULL) return;
     if(root->left == NULL && root->right == NULL) return;
     if(root->left != NULL)
         connect_next(root->left, root);
     if(root->right != NULL)
         connect_next(root->right, root->next);
     connect(root->right);
     connect(root->left);
 }
Esempio n. 2
0
void
IghtConnectionState::handle_event(bufferevent *bev, short what, void *opaque)
{
	auto self = (IghtConnectionState *) opaque;

	(void) bev;  // Suppress warning about unused variable

	if (self->connecting && self->closing) {
		delete (self);
		return;
	}

	if (what & BEV_EVENT_CONNECTED) {
		self->connecting = 0;
		self->on_connect();
		return;
	}

	if (what & BEV_EVENT_EOF) {
		self->on_error(IghtError(0));
		return;
	}

	if (self->connecting) {
		ight_info("connection::handle_event - try connect next");
		self->connect_next();
		return;
	}

	// TODO: also handle the timeout

	self->on_error(IghtError(-1));
}
Esempio n. 3
0
static lcb_error_t get_refresh(clconfig_provider *provider)
{
    http_provider *http = (http_provider *)provider;

    /**
     * We want a grace interval here because we might already be fetching a
     * connection. HOWEVER we don't want to indefinitely wait on a socket
     * so we issue a timer indicating how long we expect to wait for a
     * streaming update until we get something.
     */

    /** If we need a new socket, we do connect_next. */
    if (http->connection.state == LCB_CONNSTATE_UNINIT) {
        lcb_error_t rc = connect_next(http);
        if (rc != LCB_SUCCESS) {
            http->as_errcode = rc;
            lcb_async_signal(http->as_schederr);
        }
        return rc;
    }

    lcb_timer_disarm(http->disconn_timer);
    if (http->connection.state == LCB_CONNSTATE_CONNECTED) {
        lcb_timer_rearm(http->io_timer,
                        PROVIDER_SETTING(provider, config_node_timeout));
    }
    return LCB_SUCCESS;
}
Esempio n. 4
0
/**
 * Call when there is an error in I/O. This includes read, write, connect
 * and timeouts.
 */
static lcb_error_t io_error(http_provider *http, lcb_error_t origerr)
{
    lcb_error_t err;
    lcb_conn_params params;
    char *errinfo;
    int can_retry = 0;

    close_current(http);

    params.timeout = PROVIDER_SETTING(&http->base, config_node_timeout);
    params.handler = connect_done_handler;

    if (http->base.parent->config) {
        can_retry = 1;
    } else if (origerr != LCB_AUTH_ERROR && origerr != LCB_BUCKET_ENOENT) {
        can_retry = 1;
    }
    if (can_retry) {
        err = lcb_connection_next_node(
                &http->connection, http->nodes, &params, &errinfo);
    } else {
        err = origerr;
    }

    if (err != LCB_SUCCESS) {
        lcb_confmon_provider_failed(&http->base, origerr);
        lcb_timer_disarm(http->io_timer);
        if (is_v220_compat(http)) {
            lcb_log(LOGARGS(http, INFO),
                    "HTTP node list finished. Looping again (disconn_tmo=-1)");
            connect_next(http);
        }
        return origerr;
    } else {
        setup_request_header(http);
    }
    return LCB_SUCCESS;
}
Esempio n. 5
0
void
IghtConnectionState::handle_resolve(int result, char type, int count,
    int ttl, void *addresses, void *opaque)
{
	auto self = (IghtConnectionState *) opaque;
	const char *_family;
	const char *p;
	int error, family, size;
	char string[128];

	(void) ttl;

	ight_info("handle_resolve - enter");

	if (!self->connecting)
		abort();

	if (self->closing) {
		delete (self);
		return;
	}

	if (result != DNS_ERR_NONE)
		goto finally;

	switch (type) {
	case DNS_IPv4_A:
		ight_info("handle_resolve - IPv4");
		family = PF_INET;
		_family = "PF_INET";
		size = 4;
		break;
	case DNS_IPv6_AAAA:
		ight_info("handle_resolve - IPv6");
		family = PF_INET6;
		_family = "PF_INET6";
		size = 16;
		break;
	default:
		abort();
	}

	while (--count >= 0) {
		if (count > INT_MAX / size) {
			continue;
		}
		// Note: address already in network byte order
		p = inet_ntop(family, (char *)addresses + count * size,
		    string, sizeof (string));
		if (p == NULL) {
			ight_warn("handle_resolve - inet_ntop() failed");
			continue;
		}
		ight_info("handle_resolve - address %s", p);
		error = self->addrlist->append(string);
		if (error != 0) {
			ight_warn("handle_resolve - cannot append");
			continue;
		}
		ight_info("handle_resolve - family %s", _family);
		error = self->pflist->append(_family);
		if (error != 0) {
			ight_warn("handle_resolve - cannot append");
			// Oops the two vectors are not in sync anymore now
			self->connecting = 0;
			self->on_error(IghtError(-3));
			return;
		}
	}

    finally:
	auto dns_base = ight_get_global_evdns_base();

	if (self->must_resolve_ipv6) {
		self->must_resolve_ipv6 = 0;
		evdns_request *request = evdns_base_resolve_ipv6(dns_base,
		    self->address, DNS_QUERY_NO_SEARCH, self->handle_resolve,
		    self);
		if (request != NULL)
			return;
		/* FALLTHROUGH */
	}
	if (self->must_resolve_ipv4) {
		self->must_resolve_ipv4 = 0;
		evdns_request *request = evdns_base_resolve_ipv4(dns_base,
		    self->address, DNS_QUERY_NO_SEARCH, self->handle_resolve,
		    self);
		if (request != NULL)
			return;
		/* FALLTHROUGH */
	}
	self->connect_next();
}