/* * Copyright (c) 2016 Intel Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include void netz_host(struct netz_ctx_t *ctx, struct net_addr *host) { return netz_host_ipv4(ctx, host->in_addr.in4_u.u4_addr8[0], host->in_addr.in4_u.u4_addr8[1], host->in_addr.in4_u.u4_addr8[2], host->in_addr.in4_u.u4_addr8[3]); } void netz_host_ipv4(struct netz_ctx_t *ctx, uint8_t a1, uint8_t a2, uint8_t a3, uint8_t a4) { uip_ipaddr_t host_addr; uip_ipaddr(&host_addr, a1, a2, a3, a4); uip_sethostaddr(&host_addr); ctx->host.in_addr.in4_u.u4_addr8[0] = a1; ctx->host.in_addr.in4_u.u4_addr8[1] = a2; ctx->host.in_addr.in4_u.u4_addr8[2] = a3; ctx->host.in_addr.in4_u.u4_addr8[3] = a4; ctx->host.family = AF_INET; } void netz_netmask(struct netz_ctx_t *ctx, struct net_addr *netmask) { return netz_netmask_ipv4(ctx, netmask->in_addr.in4_u.u4_addr8[0], netmask->in_addr.in4_u.u4_addr8[1], netmask->in_addr.in4_u.u4_addr8[2], netmask->in_addr.in4_u.u4_addr8[3]); } void netz_netmask_ipv4(struct netz_ctx_t *ctx, uint8_t n1, uint8_t n2, uint8_t n3, uint8_t n4) { ARG_UNUSED(ctx); uip_ipaddr_t netmask; uip_ipaddr(&netmask, n1, n2, n3, n4); uip_setnetmask(&netmask); } void netz_remote(struct netz_ctx_t *ctx, struct net_addr *remote, int port) { return netz_remote_ipv4(ctx, remote->in_addr.in4_u.u4_addr8[0], remote->in_addr.in4_u.u4_addr8[1], remote->in_addr.in4_u.u4_addr8[2], remote->in_addr.in4_u.u4_addr8[3], port); } void netz_remote_ipv4(struct netz_ctx_t *ctx, uint8_t a1, uint8_t a2, uint8_t a3, uint8_t a4, int port) { ctx->remote.in_addr.in4_u.u4_addr8[0] = a1; ctx->remote.in_addr.in4_u.u4_addr8[1] = a2; ctx->remote.in_addr.in4_u.u4_addr8[2] = a3; ctx->remote.in_addr.in4_u.u4_addr8[3] = a4; ctx->remote.family = AF_INET; ctx->remote_port = port; } static int netz_prepare(struct netz_ctx_t *ctx, enum ip_protocol proto) { #ifdef CONFIG_NETWORKING_WITH_TCP struct app_buf_t buf = APP_BUF_INIT(NULL, 0, 0); int rc; #endif ctx->connected = 0; ctx->proto = proto; ctx->net_ctx = net_context_get(ctx->proto, &ctx->remote, ctx->remote_port, &ctx->host, 0); if (ctx->net_ctx == NULL) { return -EINVAL; } #ifdef CONFIG_NETWORKING_WITH_TCP /* workaround to activate the IP stack */ rc = netz_tx(ctx, &buf); if (rc != 0) { return rc; } #endif ctx->connected = 1; return 0; } int netz_tcp(struct netz_ctx_t *ctx) { return netz_prepare(ctx, IPPROTO_TCP); } int netz_udp(struct netz_ctx_t *ctx) { return netz_prepare(ctx, IPPROTO_UDP); } static void netz_sleep(int sleep_ticks) { struct nano_timer timer; nano_timer_init(&timer, NULL); nano_fiber_timer_start(&timer, sleep_ticks); nano_fiber_timer_test(&timer, TICKS_UNLIMITED); } static int tcp_tx(struct net_context *ctx, uint8_t *buf, size_t size, int tx_retry_timeout) { struct net_buf *nbuf; uint8_t *ptr; int rc; nbuf = ip_buf_get_tx(ctx); if (nbuf == NULL) { return -EINVAL; } ptr = net_buf_add(nbuf, size); memcpy(ptr, buf, size); ip_buf_appdatalen(nbuf) = size; do { rc = net_send(nbuf); if (rc >= 0) { ip_buf_unref(nbuf); return 0; } switch (rc) { case -EINPROGRESS: netz_sleep(tx_retry_timeout); break; case -EAGAIN: case -ECONNRESET: netz_sleep(tx_retry_timeout); break; default: ip_buf_unref(nbuf); return -EIO; } } while (1); return 0; } static int tcp_rx(struct net_context *ctx, uint8_t *buf, size_t *read_bytes, size_t size, int rx_timeout) { struct net_buf *nbuf; int rc; nbuf = net_receive(ctx, rx_timeout); if (nbuf == NULL) { return -EIO; } *read_bytes = ip_buf_appdatalen(nbuf); if (*read_bytes > size) { *read_bytes = size; rc = -ENOMEM; } else { rc = 0; } memcpy(buf, ip_buf_appdata(nbuf), *read_bytes); ip_buf_unref(nbuf); return rc; } int netz_tx(struct netz_ctx_t *ctx, struct app_buf_t *buf) { int rc; /* We don't evaluate if we are connected. */ rc = tcp_tx(ctx->net_ctx, buf->buf, buf->length, ctx->tx_retry_timeout); return rc; } int netz_rx(struct netz_ctx_t *ctx, struct app_buf_t *buf) { int rc; if (ctx->connected != 1) { return -ENOTCONN; } rc = tcp_rx(ctx->net_ctx, buf->buf, &buf->length, buf->size, ctx->rx_timeout); return rc; }