static void on_connect(h2o_socket_t *sock, const char *err) { h2o_socketpool_connect_request_t *req = sock->data; const char *errstr = NULL; assert(req->sock == sock); if (err != NULL) { __sync_sub_and_fetch(&req->pool->targets.entries[req->selected_target]->_shared.leased_count, 1); h2o_socket_close(sock); if (req->remaining_try_count == 0) { req->sock = NULL; errstr = "connection failed"; /* shouldn't we return err? */ } else { try_connect(req); return; } } else { h2o_url_t *target_url = &req->pool->targets.entries[req->selected_target]->url; if (target_url->scheme->is_ssl) { assert(req->pool->_ssl_ctx != NULL && "h2o_socketpool_set_ssl_ctx must be called for a pool that contains SSL target"); h2o_socket_ssl_handshake(sock, req->pool->_ssl_ctx, target_url->host.base, on_handshake_complete); return; } } call_connect_cb(req, errstr); }
static void start_connect(h2o_socketpool_connect_request_t *req, struct sockaddr *addr, socklen_t addrlen) { req->sock = h2o_socket_connect(req->loop, addr, addrlen, on_connect); if (req->sock == NULL) { __sync_sub_and_fetch(&req->pool->_shared.count, 1); call_connect_cb(req, "failed to connect to host"); return; } req->sock->data = req; req->sock->on_close.cb = on_close; req->sock->on_close.data = req->pool; }
static void on_connect(h2o_socket_t *sock, int status) { h2o_socketpool_connect_request_t *req = sock->data; const char *errstr = NULL; assert(req->sock == sock); if (status != 0) { h2o_socket_close(sock); req->sock = NULL; errstr = "connection failed"; } call_connect_cb(req, errstr); }
static void on_getaddr(h2o_hostinfo_getaddr_req_t *getaddr_req, const char *errstr, struct addrinfo *res) { h2o_socketpool_connect_request_t *req = H2O_STRUCT_FROM_MEMBER(h2o_socketpool_connect_request_t, getaddr_req, getaddr_req); if (errstr != NULL) { __sync_sub_and_fetch(&req->pool->_shared.count, 1); call_connect_cb(req, errstr); return; } struct addrinfo *selected = h2o_hostinfo_select_one(res); start_connect(req, selected->ai_addr, selected->ai_addrlen); freeaddrinfo(res); }
static void on_handshake_complete(h2o_socket_t *sock, const char *err) { h2o_socketpool_connect_request_t *req = sock->data; assert(req->sock == sock); if (err == h2o_socket_error_ssl_cert_name_mismatch && (SSL_CTX_get_verify_mode(req->pool->_ssl_ctx) & SSL_VERIFY_PEER) == 0) { /* ignore CN mismatch if we are not verifying peer */ } else if (err != NULL) { h2o_socket_close(sock); req->sock = NULL; } call_connect_cb(req, err); }
static void on_getaddr(h2o_hostinfo_getaddr_req_t *getaddr_req, const char *errstr, struct addrinfo *res, void *_req) { h2o_socketpool_connect_request_t *req = _req; assert(getaddr_req == req->getaddr_req); req->getaddr_req = NULL; if (errstr != NULL) { __sync_sub_and_fetch(&req->pool->_shared.count, 1); call_connect_cb(req, errstr); return; } struct addrinfo *selected = h2o_hostinfo_select_one(res); start_connect(req, selected->ai_addr, selected->ai_addrlen); }
static void start_connect(h2o_socketpool_connect_request_t *req, struct sockaddr *addr, socklen_t addrlen) { struct on_close_data_t *close_data; req->sock = h2o_socket_connect(req->loop, addr, addrlen, on_connect); if (req->sock == NULL) { __sync_sub_and_fetch(&req->pool->targets.entries[req->selected_target]->_shared.leased_count, 1); if (req->remaining_try_count > 0) { try_connect(req); return; } __sync_sub_and_fetch(&req->pool->_shared.count, 1); call_connect_cb(req, "failed to connect to host"); return; } close_data = h2o_mem_alloc(sizeof(*close_data)); close_data->pool = req->pool; close_data->target = req->selected_target; req->sock->data = req; req->sock->on_close.cb = on_close; req->sock->on_close.data = close_data; }