net: app: client: Allow net_context re-connect

If user closes the client connection, then make sure that
user can just call net_app_connect() instead of calling the
client init. The client initializes everything in net_app but
for simple re-connect that is not necessary.

Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
This commit is contained in:
Jukka Rissanen 2017-10-22 18:13:35 +03:00
parent aeb6a7e323
commit 9728179757
2 changed files with 127 additions and 34 deletions

View File

@ -285,6 +285,47 @@ static void close_net_ctx(struct net_app_ctx *ctx)
#endif
}
static int bind_local(struct net_app_ctx *ctx)
{
int ret = 0;
#if defined(CONFIG_NET_IPV4)
if (ctx->ipv4.remote.sa_family == AF_INET && ctx->ipv4.ctx) {
ctx->ipv4.local.sa_family = AF_INET;
_net_app_set_local_addr(&ctx->ipv4.local, NULL,
net_sin(&ctx->ipv4.local)->sin_port);
ret = _net_app_set_net_ctx(ctx, ctx->ipv4.ctx,
&ctx->ipv4.local,
sizeof(struct sockaddr_in),
ctx->proto);
if (ret < 0) {
net_context_put(ctx->ipv4.ctx);
ctx->ipv4.ctx = NULL;
}
}
#endif
#if defined(CONFIG_NET_IPV6)
if (ctx->ipv6.remote.sa_family == AF_INET6 && ctx->ipv6.ctx) {
ctx->ipv6.local.sa_family = AF_INET6;
_net_app_set_local_addr(&ctx->ipv6.local, NULL,
net_sin6(&ctx->ipv6.local)->sin6_port);
ret = _net_app_set_net_ctx(ctx, ctx->ipv6.ctx,
&ctx->ipv6.local,
sizeof(struct sockaddr_in6),
ctx->proto);
if (ret < 0) {
net_context_put(ctx->ipv6.ctx);
ctx->ipv6.ctx = NULL;
}
}
#endif
return ret;
}
int net_app_init_client(struct net_app_ctx *ctx,
enum net_sock_type sock_type,
enum net_ip_protocol proto,
@ -366,6 +407,7 @@ int net_app_init_client(struct net_app_ctx *ctx,
ctx->recv_cb = _net_app_received;
ctx->proto = proto;
ctx->sock_type = sock_type;
ctx->is_enabled = true;
ret = _net_app_config_local_ctx(ctx, sock_type, proto, &addr);
if (ret < 0) {
@ -418,39 +460,10 @@ int net_app_init_client(struct net_app_ctx *ctx,
return -EPFNOSUPPORT;
}
#if defined(CONFIG_NET_IPV4)
if (ctx->ipv4.remote.sa_family == AF_INET) {
ctx->ipv4.local.sa_family = AF_INET;
_net_app_set_local_addr(&ctx->ipv4.local, NULL,
net_sin(&ctx->ipv4.local)->sin_port);
ret = _net_app_set_net_ctx(ctx, ctx->ipv4.ctx,
&ctx->ipv4.local,
sizeof(struct sockaddr_in),
ctx->proto);
if (ret < 0) {
net_context_put(ctx->ipv4.ctx);
ctx->ipv4.ctx = NULL;
}
ret = bind_local(ctx);
if (ret < 0) {
goto fail;
}
#endif
#if defined(CONFIG_NET_IPV6)
if (ctx->ipv6.remote.sa_family == AF_INET6) {
ctx->ipv6.local.sa_family = AF_INET6;
_net_app_set_local_addr(&ctx->ipv6.local, NULL,
net_sin6(&ctx->ipv6.local)->sin6_port);
ret = _net_app_set_net_ctx(ctx, ctx->ipv6.ctx,
&ctx->ipv6.local,
sizeof(struct sockaddr_in6),
ctx->proto);
if (ret < 0) {
net_context_put(ctx->ipv6.ctx);
ctx->ipv6.ctx = NULL;
}
}
#endif
_net_app_print_info(ctx);
@ -605,6 +618,27 @@ int net_app_connect(struct net_app_ctx *ctx, s32_t timeout)
return -EAFNOSUPPORT;
}
if (!ctx->is_enabled) {
NET_DBG("Re-connecting to net_ctx %p", net_ctx);
ret = _net_app_config_local_ctx(ctx, ctx->sock_type,
ctx->proto, NULL);
if (ret < 0) {
NET_DBG("Cannot get local endpoint (%d)", ret);
return -EINVAL;
}
ret = bind_local(ctx);
if (ret < 0) {
NET_DBG("Cannot bind local endpoint (%d)", ret);
return -EINVAL;
}
ctx->is_enabled = true;
_net_app_print_info(ctx);
}
#if defined(CONFIG_NET_APP_TLS) || defined(CONFIG_NET_APP_DTLS)
if (ctx->is_tls && !ctx->tls.tid &&
(ctx->proto == IPPROTO_TCP ||

View File

@ -63,6 +63,11 @@ static void net_app_foreach(net_app_ctx_cb_t cb, enum net_app_type type,
SYS_SLIST_FOR_EACH_CONTAINER(&_net_app_instances, ctx, node) {
if (ctx->is_init && ctx->app_type == type) {
if (ctx->app_type == NET_APP_CLIENT &&
!ctx->is_enabled) {
continue;
}
cb(ctx, user_data);
}
}
@ -379,6 +384,11 @@ int _net_app_config_local_ctx(struct net_app_ctx *ctx,
ret = -EPFNOSUPPORT;
goto fail;
}
if (!ret) {
select_default_ctx(ctx);
return 0;
}
#endif
#if defined(CONFIG_NET_IPV4)
@ -389,9 +399,12 @@ int _net_app_config_local_ctx(struct net_app_ctx *ctx,
ret = -EPFNOSUPPORT;
goto fail;
}
#endif
select_default_ctx(ctx);
if (!ret) {
select_default_ctx(ctx);
return 0;
}
#endif
} else {
if (addr->sa_family == AF_INET6) {
#if defined(CONFIG_NET_IPV6)
@ -999,8 +1012,34 @@ int net_app_close(struct net_app_ctx *ctx)
if (net_ctx) {
net_ctx->net_app = NULL;
net_context_put(net_ctx);
NET_DBG("Closing net_ctx %p", net_ctx);
}
#if defined(CONFIG_NET_APP_CLIENT)
if (ctx->app_type == NET_APP_CLIENT) {
ctx->is_enabled = false;
/* Make sure we do not re-use the same port if we
* re-connect after close.
*/
#if defined(CONFIG_NET_IPV4)
net_sin(&ctx->ipv4.local)->sin_port = 0;
if (ctx->ipv4.ctx) {
net_sin_ptr(&ctx->ipv4.ctx->local)->sin_port = 0;
}
#endif
#if defined(CONFIG_NET_IPV6)
net_sin6(&ctx->ipv6.local)->sin6_port = 0;
if (ctx->ipv6.ctx) {
net_sin6_ptr(&ctx->ipv6.ctx->local)->sin6_port = 0;
}
#endif
}
#endif
return 0;
}
@ -1043,6 +1082,26 @@ int net_app_close2(struct net_app_ctx *ctx, struct net_context *net_ctx)
if (net_ctx != _net_app_select_net_ctx(ctx, NULL)) {
return -ENOENT;
}
ctx->is_enabled = false;
/* Make sure we do not re-use the same port if we
* re-connect after close.
*/
#if defined(CONFIG_NET_IPV4)
net_sin(&ctx->ipv4.local)->sin_port = 0;
if (net_ctx == ctx->ipv4.ctx) {
net_sin_ptr(&ctx->ipv4.ctx->local)->sin_port = 0;
}
#endif
#if defined(CONFIG_NET_IPV6)
net_sin6(&ctx->ipv6.local)->sin6_port = 0;
if (net_ctx == ctx->ipv6.ctx) {
net_sin6_ptr(&ctx->ipv6.ctx->local)->sin6_port = 0;
}
#endif
}
#endif