Commit 29be96d7 authored by Jacek Kalwas's avatar Jacek Kalwas Committed by Tomasz Zawadzki
Browse files

sock/posix: add spdk_sock_connect_async

Motivation to introduce this function is to prevent blocking behavior.
Compared to spdk_sock_connect[_ext] there is no functional change
from user perspective.

For detals see previous patch 2dff9736.

Change inspired by:
https://review.spdk.io/c/spdk/spdk/+/9508



Connection is initiated by connect_async and advanced on
- flush (also used by writev_async)
- readv (also used by recv[_next])
until it is established or failed; these functions already cover
retryable errors so there should be no impact on users.

When using connect_async
  - group_impl_add_sock
  - set_recvlowat
  - set_[recv|send]buf
are internally deferred until connection is established,
  - group_impl_get_optimal
  - is_connected
  - is_ipv[4|6]
  - getaddr
retrun error if invoked and connection was not established,
  - close
  - group_impl_remove_sock
introduce additional connection state checks
  - get_interface_name
  - get_numa_id
  - others
are not affected.

Fixes #2062.

Change-Id: Ice40ee21dcf236a19108cfff5afcc445f702d16f
Signed-off-by: default avatarJacek Kalwas <jacek.kalwas@nutanix.com>
Reviewed-on: https://review.spdk.io/c/spdk/spdk/+/25907


Reviewed-by: default avatarTomasz Zawadzki <tomasz@tzawadzki.com>
Reviewed-by: default avatarJim Harris <jim.harris@nvidia.com>
Tested-by: default avatarSPDK Automated Test System <spdkbot@gmail.com>
Community-CI: Mellanox Build Bot
Community-CI: Broadcom CI <spdk-ci.pdl@broadcom.com>
parent 676041ea
Loading
Loading
Loading
Loading
+43 −0
Original line number Diff line number Diff line
@@ -275,6 +275,8 @@ void spdk_sock_get_default_opts(struct spdk_sock_opts *opts);
/**
 * Get client and server addresses of the given socket.
 *
 * This function is allowed only when connection is established.
 *
 * Returning -1 and setting errno is deprecated and will be changed in the 26.01 release.
 * This function will return negative errno values instead.
 *
@@ -328,6 +330,41 @@ struct spdk_sock *spdk_sock_connect(const char *ip, int port, const char *impl_n
struct spdk_sock *spdk_sock_connect_ext(const char *ip, int port, const char *impl_name,
					struct spdk_sock_opts *opts);

/**
 * Signature for callback function invoked when a connection is completed.
 *
 * \param cb_arg Context specified by \ref spdk_sock_connect_async.
 * \param status 0 on success, negative errno value on failure.
 */
typedef void (*spdk_sock_connect_cb_fn)(void *cb_arg, int status);

/**
 * Create a socket using the specific sock implementation, initiate the socket connection
 * to the specified address and port (of the server), and then return the socket.
 * This function is used by client.
 *
 * Not every function with sock object on the interface is allowed if the conncection is not
 * established. In order to determine connection status use \p cb_fn. Functions taking sock
 * object as an input may return EAGAIN to indicate connection is in progress or other
 * errno values if connection failed.
 *
 * Callback function \p cb_fn is invoked only if this function returns a non-NULL value.
 * However, if async connect is not supported by the \p impl_name it fallbacks to the sync
 * version and \p cb_fn will be invoked only if sync connect is successful and before
 * returning control to the the user.
 *
 * \param ip IP address of the server.
 * \param port Port number of the server.
 * \param impl_name The sock implementation to use, such as "posix", or NULL for default.
 * \param opts The sock option pointer provided by the user which should not be NULL pointer.
 * \param cb_fn Callback function invoked when the connection attempt is completed. (optional)
 * \param cb_arg Argument passed to callback function. (optional)
 *
 * \return a pointer to the socket on success, or NULL on failure.
 */
struct spdk_sock *spdk_sock_connect_async(const char *ip, int port, const char *impl_name,
		struct spdk_sock_opts *opts, spdk_sock_connect_cb_fn cb_fn, void *cb_arg);

/**
 * Create a socket using the specific sock implementation, bind the socket to
 * the specified address and port and listen on the socket, and then return the socket.
@@ -539,6 +576,8 @@ int spdk_sock_set_sendbuf(struct spdk_sock *sock, int sz);
/**
 * Check whether the address of socket is ipv6.
 *
 * This function is allowed only when connection is established.
 *
 * \param sock Socket to check.
 *
 * \return true if the address of socket is ipv6, or false otherwise.
@@ -548,6 +587,8 @@ bool spdk_sock_is_ipv6(struct spdk_sock *sock);
/**
 * Check whether the address of socket is ipv4.
 *
 * This function is allowed only when connection is established.
 *
 * \param sock Socket to check.
 *
 * \return true if the address of socket is ipv4, or false otherwise.
@@ -671,6 +712,8 @@ int spdk_sock_group_close(struct spdk_sock_group **group);
/**
 * Get the optimal sock group for this sock.
 *
 * This function is allowed only when connection is established.
 *
 * Returning -1 and setting errno is deprecated and will be changed in the 26.01 release.
 * This function will return negative errno values instead.
 *
+2 −0
Original line number Diff line number Diff line
@@ -83,6 +83,8 @@ struct spdk_net_impl {
	const char *(*get_interface_name)(struct spdk_sock *sock);
	int32_t (*get_numa_id)(struct spdk_sock *sock);
	struct spdk_sock *(*connect)(const char *ip, int port, struct spdk_sock_opts *opts);
	struct spdk_sock *(*connect_async)(const char *ip, int port, struct spdk_sock_opts *opts,
					   spdk_sock_connect_cb_fn cb_fn, void *cb_arg);
	struct spdk_sock *(*listen)(const char *ip, int port, struct spdk_sock_opts *opts);
	struct spdk_sock *(*accept)(struct spdk_sock *sock);
	int (*close)(struct spdk_sock *sock);
+30 −3
Original line number Diff line number Diff line
@@ -607,14 +607,17 @@ spdk_sock_connect(const char *ip, int port, const char *impl_name)
	return spdk_sock_connect_ext(ip, port, impl_name, &opts);
}

struct spdk_sock *
spdk_sock_connect_ext(const char *ip, int port, const char *_impl_name, struct spdk_sock_opts *opts)
static struct spdk_sock *
sock_connect_ext(const char *ip, int port, const char *_impl_name, struct spdk_sock_opts *opts,
		 bool async, spdk_sock_connect_cb_fn cb_fn, void *cb_arg)
{
	struct spdk_net_impl *impl = NULL;
	struct spdk_sock *sock;
	struct spdk_sock_opts opts_local;
	const char *impl_name = NULL;

	assert(async || (!cb_fn && !cb_arg));

	if (opts == NULL) {
		SPDK_ERRLOG("the opts should not be NULL pointer\n");
		return NULL;
@@ -644,7 +647,12 @@ spdk_sock_connect_ext(const char *ip, int port, const char *_impl_name, struct s
		return NULL;
	}

	if (async && impl->connect_async) {
		sock = impl->connect_async(ip, port, &opts_local, cb_fn, cb_arg);
	} else {
		sock = impl->connect(ip, port, &opts_local);
	}

	if (!sock) {
		return NULL;
	}
@@ -657,9 +665,28 @@ spdk_sock_connect_ext(const char *ip, int port, const char *_impl_name, struct s
	sock->net_impl = impl;
	TAILQ_INIT(&sock->queued_reqs);
	TAILQ_INIT(&sock->pending_reqs);

	/* Invoke cb_fn only in case of fallback to sync version. */
	if (cb_fn && async && !impl->connect_async) {
		cb_fn(cb_arg, 0);
	}

	return sock;
}

struct spdk_sock *
spdk_sock_connect_ext(const char *ip, int port, const char *_impl_name, struct spdk_sock_opts *opts)
{
	return sock_connect_ext(ip, port, _impl_name, opts, false, NULL, NULL);
}

struct spdk_sock *
spdk_sock_connect_async(const char *ip, int port, const char *_impl_name,
			struct spdk_sock_opts *opts, spdk_sock_connect_cb_fn cb_fn, void *cb_arg)
{
	return sock_connect_ext(ip, port, _impl_name, opts, true, cb_fn, cb_arg);
}

struct spdk_sock *
spdk_sock_listen(const char *ip, int port, const char *impl_name)
{
+1 −0
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@
	spdk_sock_get_numa_id;
	spdk_sock_connect;
	spdk_sock_connect_ext;
	spdk_sock_connect_async;
	spdk_sock_listen;
	spdk_sock_listen_ext;
	spdk_sock_accept;
+317 −42
Original line number Diff line number Diff line
@@ -37,10 +37,18 @@
#endif

struct posix_connect_ctx {
	int fd;
	bool ssl;
	struct addrinfo *first_res;
	struct addrinfo *next_res;
	struct spdk_sock_opts opts;
	struct spdk_sock_impl_opts impl_opts;
	uint64_t timeout_tsc;
	int set_recvlowat;
	int set_recvbuf;
	int set_sendbuf;
	spdk_sock_connect_cb_fn cb_fn;
	void *cb_arg;
};

struct spdk_posix_sock {
@@ -54,6 +62,7 @@ struct spdk_posix_sock {
	bool			pipe_has_data;
	bool			socket_has_data;
	bool			zcopy;
	bool			ready;

	int			placement_id;

@@ -63,6 +72,8 @@ struct spdk_posix_sock {
	TAILQ_ENTRY(spdk_posix_sock)	link;

	char			interface_name[IFNAMSIZ];

	struct posix_connect_ctx	*connect_ctx;
};

TAILQ_HEAD(spdk_has_data_list, spdk_posix_sock);
@@ -234,6 +245,12 @@ posix_sock_getaddr(struct spdk_sock *_sock, char *saddr, int slen, uint16_t *spo
{
	struct spdk_posix_sock *sock = __posix_sock(_sock);

	if (!sock->ready) {
		SPDK_ERRLOG("Connection %s.\n", sock->connect_ctx ? "in progress" : "failed");
		errno = sock->connect_ctx ? EAGAIN : ENOTCONN;
		return -1;
	}

	assert(sock != NULL);
	return spdk_net_getaddr(sock->fd, saddr, slen, sport, caddr, clen, cport);
}
@@ -363,6 +380,17 @@ posix_sock_set_recvbuf(struct spdk_sock *_sock, int sz)

	assert(sock != NULL);

	if (!sock->ready) {
		if (sock->connect_ctx) {
			sock->connect_ctx->set_recvbuf = sz;
			return 0;
		}

		SPDK_ERRLOG("Connection failed.\n");
		errno = ENOTCONN;
		return -1;
	}

	if (_sock->impl_opts.enable_recv_pipe) {
		rc = posix_sock_alloc_pipe(sock, sz);
		if (rc) {
@@ -397,6 +425,17 @@ posix_sock_set_sendbuf(struct spdk_sock *_sock, int sz)

	assert(sock != NULL);

	if (!sock->ready) {
		if (sock->connect_ctx) {
			sock->connect_ctx->set_sendbuf = sz;
			return 0;
		}

		SPDK_ERRLOG("Connection failed.\n");
		errno = ENOTCONN;
		return -1;
	}

	/* Set kernel buffer size to be at least MIN_SO_SNDBUF_SIZE and
	 * _sock->impl_opts.send_buf_size. */
	min_size = spdk_max(MIN_SO_SNDBUF_SIZE, _sock->impl_opts.send_buf_size);
@@ -455,6 +494,7 @@ posix_sock_init(struct spdk_posix_sock *sock, bool enable_zero_copy)
		spdk_sock_map_insert(&g_map, sock->placement_id, NULL);
	}
#endif
	sock->ready = true;
}

static struct spdk_posix_sock *
@@ -953,10 +993,12 @@ retry:
}

static int
_sock_posix_connect(struct posix_connect_ctx *ctx)
_sock_posix_connect_async(struct posix_connect_ctx *ctx)
{
	int rc, fd = -1;
	int rc = -ENOENT, fd;

	/* It is either first execution or continuation; in that case invalid fd is expected. */
	assert(ctx->fd == -1);
	for (; ctx->next_res != NULL; ctx->next_res = ctx->next_res->ai_next) {
		rc = spdk_sock_posix_fd_create(ctx->next_res, &ctx->opts, &ctx->impl_opts);
		if (rc < 0) {
@@ -964,52 +1006,87 @@ _sock_posix_connect(struct posix_connect_ctx *ctx)
		}

		fd = rc;
		rc = spdk_sock_posix_fd_connect(fd, ctx->next_res, &ctx->opts);
		rc = spdk_sock_posix_fd_connect_async(fd, ctx->next_res, &ctx->opts);
		if (rc < 0) {
			close(fd);
			fd = -1;
			continue;
		}

		ctx->next_res = ctx->next_res->ai_next;
		break;
	}

	if (rc < 0) {
		return rc;
	}

	ctx->fd = fd;
	ctx->timeout_tsc = !ctx->opts.connect_timeout ? 0 : spdk_get_ticks() + ctx->opts.connect_timeout *
			   spdk_get_ticks_hz() / 1000;
	return 0;
}

static void
sock_posix_connect_ctx_cleanup(struct posix_connect_ctx **_ctx, int rc)
{
	struct posix_connect_ctx *ctx = *_ctx;

	*_ctx = NULL;
	if (!ctx) {
		return;
	}

	freeaddrinfo(ctx->first_res);
	return fd;
	if (ctx->cb_fn) {
		ctx->cb_fn(ctx->cb_arg, rc);
	}

	free(ctx);
}

static int
sock_posix_connect(struct addrinfo *res, struct spdk_sock_opts *opts,
		   struct spdk_sock_impl_opts *impl_opts)
sock_posix_connect_async(struct addrinfo *res, struct spdk_sock_opts *opts,
			 struct spdk_sock_impl_opts *impl_opts, bool ssl, spdk_sock_connect_cb_fn cb_fn, void *cb_arg,
			 struct posix_connect_ctx **_ctx)
{
	struct posix_connect_ctx *ctx;
	int rc;

	ctx = calloc(1, sizeof(*ctx));
	if (!ctx) {
		return -1;
		return -ENOMEM;
	}

	ctx->first_res = ctx->next_res = res;
	ctx->opts = *opts;
	ctx->impl_opts = *impl_opts;

	rc = _sock_posix_connect(ctx);
	ctx->ssl = ssl;
	ctx->fd = -1;
	ctx->set_recvlowat = -1;
	ctx->set_recvbuf = -1;
	ctx->set_sendbuf = -1;
	ctx->cb_fn = cb_fn;
	ctx->cb_arg = cb_arg;

	rc = _sock_posix_connect_async(ctx);
	if (rc < 0) {
		free(ctx);
		return -1;
		return rc;
	}

	free(ctx);
	return rc;
	*_ctx = ctx;
	return 0;
}

static int posix_connect_poller(struct spdk_posix_sock *sock);

static struct spdk_sock *
_posix_sock_connect(const char *ip, int port, struct spdk_sock_opts *opts, bool enable_ssl)
_posix_sock_connect(const char *ip, int port, struct spdk_sock_opts *opts, bool async,
		    bool enable_ssl, spdk_sock_connect_cb_fn cb_fn, void *cb_arg)
{
	struct spdk_sock_impl_opts impl_opts;
	struct spdk_posix_sock *sock;
	struct addrinfo *res0;
	struct spdk_posix_sock *sock = NULL;
	struct addrinfo *res0 = NULL;
	int rc;

	assert(opts != NULL);
@@ -1021,44 +1098,48 @@ _posix_sock_connect(const char *ip, int port, struct spdk_sock_opts *opts, bool

	res0 = spdk_sock_posix_getaddrinfo(ip, port);
	if (!res0) {
		return NULL;
		rc = -EIO;
		goto err;
	}

	sock = posix_sock_alloc(-1, &impl_opts);
	if (!sock) {
		return NULL;
	}

	sock->fd = sock_posix_connect(res0, opts, &impl_opts);
	if (sock->fd < 0) {
		rc = -ENOMEM;
		goto err;
	}

	if (enable_ssl) {
		rc = posix_sock_configure_ssl(sock, true);
	rc = sock_posix_connect_async(res0, opts, &impl_opts, enable_ssl, cb_fn, cb_arg,
				      &sock->connect_ctx);
	if (rc < 0) {
		goto err;
	}

	sock->fd = sock->connect_ctx->fd;
	if (async) {
		return &sock->base;
	}

	if (spdk_fd_set_nonblock(sock->fd)) {
		goto err;
	do {
		rc = posix_connect_poller(sock);
	} while (rc == -EAGAIN);

	if (!sock->ready) {
		free(sock);
		return NULL;
	}

	/* Only enable zero copy for non-loopback and non-ssl sockets. */
	posix_sock_init(sock, opts->zcopy && !spdk_net_is_loopback(sock->fd) && !enable_ssl &&
			impl_opts.enable_zerocopy_send_client);
	return &sock->base;

err:
	/* It is safe to pass NULL to SSL free functions. */
	SSL_free(sock->ssl);
	SSL_CTX_free(sock->ssl_ctx);
	if (sock->fd != -1) {
		close(sock->fd);
	free(sock);
	if (res0) {
		freeaddrinfo(res0);
	}

	if (cb_fn) {
		cb_fn(cb_arg, rc);
	}

	free(sock);
	return NULL;
}

@@ -1071,7 +1152,14 @@ posix_sock_listen(const char *ip, int port, struct spdk_sock_opts *opts)
static struct spdk_sock *
posix_sock_connect(const char *ip, int port, struct spdk_sock_opts *opts)
{
	return _posix_sock_connect(ip, port, opts, false);
	return _posix_sock_connect(ip, port, opts, false, false, NULL, NULL);
}

static struct spdk_sock *
posix_sock_connect_async(const char *ip, int port, struct spdk_sock_opts *opts,
			 spdk_sock_connect_cb_fn cb_fn, void *cb_arg)
{
	return _posix_sock_connect(ip, port, opts, true, false, cb_fn, cb_arg);
}

static struct spdk_sock *
@@ -1153,6 +1241,8 @@ posix_sock_close(struct spdk_sock *_sock)

	assert(TAILQ_EMPTY(&_sock->pending_reqs));

	sock_posix_connect_ctx_cleanup(&sock->connect_ctx, -ECONNRESET);

	if (sock->ssl != NULL) {
		SSL_shutdown(sock->ssl);
	}
@@ -1160,15 +1250,19 @@ posix_sock_close(struct spdk_sock *_sock)
	/* If the socket fails to close, the best choice is to
	 * leak the fd but continue to free the rest of the sock
	 * memory. */
	if (sock->fd != -1) {
		close(sock->fd);
	}

	SSL_free(sock->ssl);
	SSL_CTX_free(sock->ssl_ctx);

	if (sock->recv_pipe) {
		pipe_buf = spdk_pipe_destroy(sock->recv_pipe);
		free(pipe_buf);
	free(sock);
	}

	free(sock);
	return 0;
}

@@ -1287,6 +1381,12 @@ _sock_flush(struct spdk_sock *sock)
	size_t len;
	bool is_zcopy = false;

	rc = posix_connect_poller(psock);
	if (rc < 0) {
		errno = -rc;
		return -1;
	}

	/* Can't flush from within a callback or we end up with recursive calls */
	if (sock->cb_cnt > 0) {
		errno = EAGAIN;
@@ -1510,6 +1610,12 @@ posix_sock_readv(struct spdk_sock *_sock, struct iovec *iov, int iovcnt)
	int rc, i;
	size_t len;

	rc = posix_connect_poller(sock);
	if (rc < 0) {
		errno = -rc;
		return -1;
	}

	if (sock->recv_pipe == NULL) {
		assert(sock->pipe_has_data == false);
		if (group && sock->socket_has_data) {
@@ -1642,6 +1748,17 @@ posix_sock_set_recvlowat(struct spdk_sock *_sock, int nbytes)

	assert(sock != NULL);

	if (!sock->ready) {
		if (sock->connect_ctx) {
			sock->connect_ctx->set_recvlowat = nbytes;
			return 0;
		}

		SPDK_ERRLOG("Connection failed.\n");
		errno = ENOTCONN;
		return -1;
	}

	val = nbytes;
	return setsockopt(sock->fd, SOL_SOCKET, SO_RCVLOWAT, &val, sizeof val);
}
@@ -1656,6 +1773,12 @@ posix_sock_is_ipv6(struct spdk_sock *_sock)

	assert(sock != NULL);

	if (!sock->ready) {
		SPDK_ERRLOG("Connection %s.\n", sock->connect_ctx ? "in progress" : "failed");
		errno = sock->connect_ctx ? EAGAIN : ENOTCONN;
		return -1;
	}

	memset(&sa, 0, sizeof sa);
	salen = sizeof sa;
	rc = getsockname(sock->fd, (struct sockaddr *) &sa, &salen);
@@ -1677,6 +1800,12 @@ posix_sock_is_ipv4(struct spdk_sock *_sock)

	assert(sock != NULL);

	if (!sock->ready) {
		SPDK_ERRLOG("Connection %s.\n", sock->connect_ctx ? "in progress" : "failed");
		errno = sock->connect_ctx ? EAGAIN : ENOTCONN;
		return -1;
	}

	memset(&sa, 0, sizeof sa);
	salen = sizeof sa;
	rc = getsockname(sock->fd, (struct sockaddr *) &sa, &salen);
@@ -1695,6 +1824,12 @@ posix_sock_is_connected(struct spdk_sock *_sock)
	uint8_t byte;
	int rc;

	rc = posix_connect_poller(sock);
	if (rc < 0) {
		errno = -rc;
		return false;
	}

	rc = recv(sock->fd, &byte, 1, MSG_PEEK);
	if (rc == 0) {
		return false;
@@ -1717,6 +1852,12 @@ posix_sock_group_impl_get_optimal(struct spdk_sock *_sock, struct spdk_sock_grou
	struct spdk_posix_sock *sock = __posix_sock(_sock);
	struct spdk_sock_group_impl *group_impl;

	if (!sock->ready) {
		SPDK_ERRLOG("Connection %s.\n", sock->connect_ctx ? "in progress" : "failed");
		errno = sock->connect_ctx ? EAGAIN : ENOTCONN;
		return NULL;
	}

	if (sock->placement_id != -1) {
		spdk_sock_map_lookup(&g_map, sock->placement_id, &group_impl, hint);
		return group_impl;
@@ -1839,6 +1980,18 @@ posix_sock_group_impl_add_sock(struct spdk_sock_group_impl *_group, struct spdk_
	struct spdk_posix_sock *sock = __posix_sock(_sock);
	int rc;

	if (!sock->ready) {
		/* Defer adding the sock to the group;
		 * the group is cached in the base object by the upper layer. */
		if (sock->connect_ctx) {
			return 0;
		}

		SPDK_ERRLOG("Connection failed.\n");
		errno = ENOTCONN;
		return -1;
	}

#if defined(SPDK_EPOLL)
	struct epoll_event event;

@@ -1892,6 +2045,11 @@ posix_sock_group_impl_remove_sock(struct spdk_sock_group_impl *_group, struct sp
	struct spdk_posix_sock *sock = __posix_sock(_sock);
	int rc;

	if (sock->connect_ctx || !sock->ready) {
		spdk_sock_abort_requests(_sock);
		return 0;
	}

	if (sock->pipe_has_data || sock->socket_has_data) {
		TAILQ_REMOVE(&group->socks_with_data, sock, link);
		sock->pipe_has_data = false;
@@ -2158,12 +2316,121 @@ ssl_sock_group_impl_close(struct spdk_sock_group_impl *_group)
	return _sock_group_impl_close(_group, g_ssl_impl_opts.enable_placement_id);
}

static int
posix_connect_poller(struct spdk_posix_sock *sock)
{
	struct posix_connect_ctx *ctx = sock->connect_ctx;
	int rc;

	if (sock->ready) {
		return 0;
	} else if (!ctx) {
		return -ENOTCONN;
	}

	if (ctx->opts.connect_timeout && ctx->timeout_tsc < spdk_get_ticks()) {
		rc = -ETIMEDOUT;
		goto err;
	}

	rc = spdk_sock_posix_fd_connect_poll_async(ctx->fd);
	if (rc == -EAGAIN) {
		return -EAGAIN;;
	}

	if (rc < 0) {
		int _rc = rc;

		close(ctx->fd);
		ctx->fd = -1;
		rc = _sock_posix_connect_async(ctx);
		if (rc < 0) {
			rc = _rc;
			goto err;
		}

		return -EAGAIN;
	}

	/* Connection established, proceed to deferred initialization. */
	sock->fd = ctx->fd;

	/* Only enable zero copy for non-loopback and non-ssl sockets. */
	posix_sock_init(sock, sock->base.opts.zcopy && !spdk_net_is_loopback(sock->fd) && !ctx->ssl &&
			sock->base.impl_opts.enable_zerocopy_send_client);

	if (ctx->ssl) {
		rc = posix_sock_configure_ssl(sock, true);
		if (rc < 0) {
			goto err;
		}
	}

	if (ctx->set_recvlowat != -1) {
		rc = posix_sock_set_recvlowat(&sock->base, ctx->set_recvlowat);
		if (rc < 0) {
			SPDK_ERRLOG("Connection was established but delayed posix_sock_set_recvlowat() failed %d (errno=%d).\n",
				    rc, errno);
			rc = -errno;
			goto err;
		}
	}

	if (ctx->set_recvbuf != -1) {
		rc = posix_sock_set_recvbuf(&sock->base, ctx->set_recvbuf);
		if (rc < 0) {
			SPDK_ERRLOG("Connection was established but delayed posix_sock_set_recvbuf() failed %d (errno=%d).\n",
				    rc, errno);
			rc = -errno;
			goto err;
		}
	}

	if (ctx->set_sendbuf != -1) {
		rc = posix_sock_set_sendbuf(&sock->base, ctx->set_sendbuf);
		if (rc < 0) {
			SPDK_ERRLOG("Connection was established but delayed posix_sock_set_sendbuf() failed %d (errno=%d).\n",
				    rc, errno);
			rc = -errno;
			goto err;
		}
	}

	if (sock->base.group_impl) {
		rc = posix_sock_group_impl_add_sock(sock->base.group_impl, &sock->base);
		if (rc) {
			SPDK_ERRLOG("Connection was established but delayed posix_sock_group_impl_add_sock() failed %d (errno=%d).\n",
				    rc, errno);
			rc = -errno;
			goto err;
		}
	}

	goto out;

err:
	/* It is safe to pass NULL to SSL free functions. */
	SSL_free(sock->ssl);
	SSL_CTX_free(sock->ssl_ctx);
	if (ctx->fd != -1) {
		close(ctx->fd);
	}

	sock->fd = -1;
	sock->ready = false;

out:
	sock_posix_connect_ctx_cleanup(&sock->connect_ctx, rc);
	return rc;
}

static struct spdk_net_impl g_posix_net_impl = {
	.name		= "posix",
	.getaddr	= posix_sock_getaddr,
	.get_interface_name = posix_sock_get_interface_name,
	.get_numa_id	= posix_sock_get_numa_id,
	.connect	= posix_sock_connect,
	.connect_async	= posix_sock_connect_async,
	.listen		= posix_sock_listen,
	.accept		= posix_sock_accept,
	.close		= posix_sock_close,
@@ -2202,7 +2469,14 @@ ssl_sock_listen(const char *ip, int port, struct spdk_sock_opts *opts)
static struct spdk_sock *
ssl_sock_connect(const char *ip, int port, struct spdk_sock_opts *opts)
{
	return _posix_sock_connect(ip, port, opts, true);
	return _posix_sock_connect(ip, port, opts, false, true, NULL, NULL);
}

static struct spdk_sock *
ssl_sock_connect_async(const char *ip, int port, struct spdk_sock_opts *opts,
		       spdk_sock_connect_cb_fn cb_fn, void *cb_arg)
{
	return _posix_sock_connect(ip, port, opts, true, true, cb_fn, cb_arg);
}

static struct spdk_sock *
@@ -2217,6 +2491,7 @@ static struct spdk_net_impl g_ssl_net_impl = {
	.get_interface_name = posix_sock_get_interface_name,
	.get_numa_id	= posix_sock_get_numa_id,
	.connect	= ssl_sock_connect,
	.connect_async	= ssl_sock_connect_async,
	.listen		= ssl_sock_listen,
	.accept		= ssl_sock_accept,
	.close		= posix_sock_close,
Loading