blob: b5314ef53ca219a35e0f670f44d89c1de5bb4278 [file] [log] [blame]
/*
* 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 <string.h>
#include <errno.h>
#include <misc/printk.h>
#include "tcp_cfg.h"
#include "tcp.h"
#include <net/ip_buf.h>
#include <net/net_core.h>
#include <net/net_socket.h>
#if !defined(CONFIG_MBEDTLS_CFG_FILE)
#include "mbedtls/config.h"
#else
#include CONFIG_MBEDTLS_CFG_FILE
#endif
#include "mbedtls/ssl.h"
uip_ipaddr_t uip_hostaddr = { {CLIENT_IPADDR0, CLIENT_IPADDR1,
CLIENT_IPADDR2, CLIENT_IPADDR3}
};
uip_ipaddr_t uip_netmask = { {NETMASK0, NETMASK1, NETMASK2, NETMASK3}
};
#define CLIENT_IP_ADDR { { { CLIENT_IPADDR0, CLIENT_IPADDR1, \
CLIENT_IPADDR2, CLIENT_IPADDR3 } } }
#define SERVER_IP_ADDR { { { SERVER_IPADDR0, SERVER_IPADDR1, \
SERVER_IPADDR2, SERVER_IPADDR3 } } }
#define INET_FAMILY AF_INET
int tcp_tx(void *context, const unsigned char *buf, size_t size)
{
struct tcp_context *ctx = context;
struct net_buf *nbuf;
uint8_t *ptr;
int rc = 0;
nbuf = ip_buf_get_tx(ctx->net_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);
fiber_sleep(TCP_RETRY_TIMEOUT);
if (rc >= 0) {
ip_buf_unref(nbuf);
return size;
}
switch (rc) {
case -EINPROGRESS:
break;
case -EAGAIN:
case -ECONNRESET:
break;
default:
ip_buf_unref(nbuf);
return -EIO;
}
} while (1);
return -EIO;
}
int tcp_rx(void *context, unsigned char *buf, size_t size)
{
struct tcp_context *ctx = context;
struct net_buf *nbuf;
int8_t *ptr;
int rc, read_bytes;
if (ctx->rx_nbuf == NULL) {
nbuf = net_receive(ctx->net_ctx, TCP_RX_TIMEOUT);
rc = -EIO;
if (nbuf != NULL) {
read_bytes = ip_buf_appdatalen(nbuf);
if (read_bytes > size) {
memcpy(buf, ip_buf_appdata(nbuf), size);
ctx->rx_nbuf = nbuf;
ctx->remaining = read_bytes - size;
return size;
} else {
memcpy(buf, ip_buf_appdata(nbuf), read_bytes);
rc = read_bytes;
}
ip_buf_unref(nbuf);
}
} else {
ptr = ip_buf_appdata(ctx->rx_nbuf);
read_bytes = ip_buf_appdatalen(ctx->rx_nbuf) - ctx->remaining;
ptr += read_bytes;
if (ctx->remaining > size) {
memcpy(buf, ptr, size);
ctx->remaining -= size;
rc = size;
} else {
read_bytes = size < ctx->remaining ? size : ctx->remaining;
memcpy(buf, ptr, read_bytes);
ip_buf_unref(ctx->rx_nbuf);
ctx->remaining = 0;
ctx->rx_nbuf = NULL;
rc = read_bytes;
}
}
return rc;
}
int tcp_init(struct tcp_context *ctx)
{
static struct in_addr server_addr = SERVER_IP_ADDR;
static struct in_addr client_addr = CLIENT_IP_ADDR;
static struct net_addr server;
static struct net_addr client;
char woke = 0;
server.in_addr = server_addr;
server.family = AF_INET;
client.in_addr = client_addr;
client.family = AF_INET;
ctx->rx_nbuf = NULL;
ctx->remaining = 0;
ctx->net_ctx = net_context_get(IPPROTO_TCP,
&server, SERVER_PORT,
&client, CLIENT_PORT);
if (ctx->net_ctx == NULL) {
return -EINVAL;
}
/* In order to stablish connection, at least one packet has to be sent,
* sending a 0 size packet is no longer possible, as noted in
* https://jira.zephyrproject.org/browse/ZEP-612 so at least one byte
* has to be sent.
*/
tcp_tx(ctx, &woke, 1);
return 0;
}