* provided method `cf_create` and running setup/connect on it.
*/
struct eyeballer {
+ const char *name;
const struct Curl_addrinfo *addr; /* List of addresses to try, not owned */
int ai_family; /* matching address family only */
cf_ip_connect_create *cf_create; /* for creating cf */
cf_ip_connect_create *cf_create;
const struct Curl_dns_entry *remotehost;
cf_connect_state state;
- struct eyeballer *baller[5];
+ struct eyeballer *baller[2];
struct eyeballer *winner;
struct curltime started;
};
if(!baller)
return CURLE_OUT_OF_MEMORY;
+ baller->name = ((ai_family == AF_INET)? "ipv4" : (
+ (ai_family == AF_INET6)? "ipv6" : "ip"));
baller->cf_create = cf_create;
baller->addr = addr;
baller->ai_family = ai_family;
if(result)
goto out;
- CF_DEBUGF(infof(data, CFMSG(cf, "eyeballer created %s"),
- baller->cf->cft->name));
/* the new filter might have sub-filters */
for(wcf = baller->cf; wcf; wcf = wcf->next) {
wcf->conn = cf->conn;
out:
if(result) {
- CF_DEBUGF(infof(data, "eyeballer failed"));
+ CF_DEBUGF(infof(data, "eyeballer[%s] failed", baller->name));
baller_close(baller, data);
}
if(cf_prev)
baller->is_done = TRUE;
}
else if(Curl_timediff(*now, ctx->started) >= baller->timeoutms) {
- infof(data, "After %" CURL_FORMAT_TIMEDIFF_T
- "ms connect time, move on!", baller->timeoutms);
+ infof(data, "%s connect timeout after %" CURL_FORMAT_TIMEDIFF_T
+ "ms, move on!", baller->name, baller->timeoutms);
#if defined(ETIMEDOUT)
baller->error = ETIMEDOUT;
#endif
continue;
if(!baller->has_started) {
- CF_DEBUGF(infof(data, CFMSG(cf, "eyeballer[%d] not started yet"), i));
++not_started;
continue;
}
baller->result = baller_connect(cf, data, baller, &now, connected);
- CF_DEBUGF(infof(data, CFMSG(cf, "eyeballer[%d] connect -> %d, "
- "connected=%d"), i, baller->result, *connected));
+ CF_DEBUGF(infof(data, CFMSG(cf, "eyeballer[%s] connect -> %d, "
+ "connected=%d"), baller->name, baller->result, *connected));
if(!baller->result) {
if(*connected) {
}
allow = Curl_timeleft(data, &now, TRUE);
baller->timeoutms = baller->addr->ai_next == NULL ? allow : allow / 2;
- CF_DEBUGF(infof(data, CFMSG(cf, "eyeballer[%d] starting"), i));
baller_start_next(cf, data, baller);
- if(!baller->is_done) {
+ if(baller->is_done) {
+ CF_DEBUGF(infof(data, CFMSG(cf, "eyeballer[%s] done"), baller->name));
+ }
+ else {
/* next attempt was started */
- CF_DEBUGF(infof(data, CFMSG(cf, "eyeballer[%d] started"), i));
+ CF_DEBUGF(infof(data, CFMSG(cf, "eyeballer[%s] trying next"),
+ baller->name));
++ongoing;
}
}
* its start delay_ms have expired */
if((baller->primary && baller->primary->is_done) ||
Curl_timediff(now, ctx->started) >= baller->delay_ms) {
- CF_DEBUGF(infof(data, CFMSG(cf, "eyeballer[%d] starting"), i));
baller_start(cf, data, baller);
- if(!baller->is_done) {
- CF_DEBUGF(infof(data, CFMSG(cf, "eyeballer[%d] has started"), i));
+ if(baller->is_done) {
+ CF_DEBUGF(infof(data, CFMSG(cf, "eyeballer[%s] done"),
+ baller->name));
+ }
+ else {
+ CF_DEBUGF(infof(data, CFMSG(cf, "eyeballer[%s] starting"),
+ baller->name));
++ongoing;
++added;
}
result = CURLE_COULDNT_CONNECT;
for(i = 0; i < sizeof(ctx->baller)/sizeof(ctx->baller[0]); i++) {
struct eyeballer *baller = ctx->baller[i];
- CF_DEBUGF(infof(data, CFMSG(cf, "eyeballer[%d] assess started=%d, "
- "result=%d"), i, baller->has_started, baller->result));
+ CF_DEBUGF(infof(data, CFMSG(cf, "eyeballer[%s] assess started=%d, "
+ "result=%d"),
+ baller->name, baller->has_started, baller->result));
if(baller && baller->has_started && baller->result) {
result = baller->result;
break;
if(!result && *done) {
DEBUGASSERT(ctx->winner);
DEBUGASSERT(ctx->winner->cf);
+ DEBUGASSERT(ctx->winner->cf->connected);
/* we have a winner. Install and activate it.
* close/free all others. */
ctx->state = SCFST_DONE;
CF_DEBUGF(infof(data, CFMSG(cf, "destroy")));
if(ctx) {
- cf_he_close(cf, data);
+ cf_he_ctx_clear(cf, data);
}
/* release any resources held in state */
Curl_safefree(ctx);
{
struct cf_setup_ctx *ctx = cf->ctx;
+ (void)data;
CF_DEBUGF(infof(data, CFMSG(cf, "destroy")));
- if(ctx) {
- cf_setup_close(cf, data);
- }
- /* release any resources held in state */
Curl_safefree(ctx);
}
struct cf_ngtcp2_ctx *ctx = cf->ctx;
struct HTTP *stream = data->req.p.http;
+ DEBUGASSERT(cf->connected);
+ DEBUGASSERT(ctx);
+ DEBUGASSERT(ctx->qconn);
+ DEBUGASSERT(ctx->h3conn);
*err = CURLE_OK;
if(!stream->memlen) {
ssize_t sent = 0;
struct HTTP *stream = data->req.p.http;
+ DEBUGASSERT(cf->connected);
+ DEBUGASSERT(ctx);
+ DEBUGASSERT(ctx->qconn);
+ DEBUGASSERT(ctx->h3conn);
*err = CURLE_OK;
if(stream->closed) {
if(recvd == -1) {
if(SOCKERRNO == EAGAIN || SOCKERRNO == EWOULDBLOCK)
break;
-
- failf(data, "ngtcp2: recvfrom() unexpectedly returned %zd", recvd);
+ if(SOCKERRNO == ECONNREFUSED) {
+ const char *r_ip;
+ int r_port;
+ Curl_cf_socket_peek(cf->next, NULL, NULL, &r_ip, &r_port);
+ failf(data, "ngtcp2: connection to %s port %u refused",
+ r_ip, r_port);
+ return CURLE_COULDNT_CONNECT;
+ }
+ failf(data, "ngtcp2: recvfrom() unexpectedly returned %zd (errno=%d)",
+ recvd, SOCKERRNO);
return CURLE_RECV_ERROR;
}
return result;
}
+ *done = FALSE;
if(!ctx->qconn) {
result = cf_connect_start(cf, data);
if(result)
goto out;
}
- *done = FALSE;
result = cf_process_ingress(cf, data);
if(result)
goto out;
out:
#ifndef CURL_DISABLE_VERBOSE_STRINGS
if(result && result != CURLE_AGAIN) {
- const struct Curl_sockaddr_ex *sockaddr;
const char *r_ip;
int r_port;
- result = Curl_cf_socket_peek(cf->next, &ctx->sockfd,
- &sockaddr, &r_ip, &r_port);
+ Curl_cf_socket_peek(cf->next, NULL, NULL, &r_ip, &r_port);
infof(data, "connect to %s port %u failed: %s",
r_ip, r_port, curl_easy_strerror(result));
}
const struct Curl_addrinfo *ai)
{
struct cf_ngtcp2_ctx *ctx = NULL;
- struct Curl_cfilter *cf = NULL, *udp_cf;
+ struct Curl_cfilter *cf = NULL, *udp_cf = NULL;
CURLcode result;
(void)data;