1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

pkg: provide sock_tcp support for lwip

This commit is contained in:
Martine Lenders 2016-09-02 19:03:35 +02:00 committed by Martine Lenders
parent e5e79c2834
commit b915d15de1
14 changed files with 1981 additions and 1 deletions

View File

@ -436,6 +436,10 @@ ifneq (,$(filter lwip_sock_ip,$(USEMODULE)))
USEMODULE += lwip_raw
endif
ifneq (,$(filter lwip_sock_tcp,$(USEMODULE)))
USEMODULE += lwip_tcp
endif
ifneq (,$(filter lwip_sock_udp,$(USEMODULE)))
USEMODULE += lwip_udp
endif

View File

@ -25,6 +25,9 @@ endif
ifneq (,$(filter lwip_sock_ip,$(USEMODULE)))
DIRS += $(RIOTBASE)/pkg/lwip/contrib/sock/ip
endif
ifneq (,$(filter lwip_sock_tcp,$(USEMODULE)))
DIRS += $(RIOTBASE)/pkg/lwip/contrib/sock/tcp
endif
ifneq (,$(filter lwip_sock_udp,$(USEMODULE)))
DIRS += $(RIOTBASE)/pkg/lwip/contrib/sock/udp
endif

View File

@ -295,6 +295,11 @@ int lwip_sock_create(struct netconn **conn, const struct _sock_tl_ep *local,
* local->port) demand binding */
if (bind) {
switch (netconn_bind(*conn, &local_addr, local_port)) {
#if LWIP_TCP
case ERR_BUF:
res = -ENOMEM;
break;
#endif
case ERR_USE:
res = -EADDRINUSE;
break;
@ -311,6 +316,24 @@ int lwip_sock_create(struct netconn **conn, const struct _sock_tl_ep *local,
}
if (remote != NULL) {
switch (netconn_connect(*conn, &remote_addr, remote_port)) {
#if LWIP_TCP
case ERR_BUF:
res = -ENOMEM;
break;
case ERR_INPROGRESS:
res = -EINPROGRESS;
break;
case ERR_ISCONN:
res = -EISCONN;
break;
case ERR_IF:
case ERR_RTE:
res = -ENETUNREACH;
break;
case ERR_ABRT:
res = -ETIMEDOUT;
break;
#endif
case ERR_USE:
res = -EADDRINUSE;
break;
@ -403,6 +426,7 @@ int lwip_sock_get_addr(struct netconn *conn, struct _sock_tl_ep *ep, u8_t local)
return 0;
}
#if defined(MODULE_LWIP_SOCK_UDP) || defined(MODULE_LWIP_SOCK_IP)
int lwip_sock_recv(struct netconn *conn, uint32_t timeout, struct netbuf **buf)
{
int res;
@ -441,6 +465,7 @@ int lwip_sock_recv(struct netconn *conn, uint32_t timeout, struct netbuf **buf)
#endif
return res;
}
#endif /* defined(MODULE_LWIP_SOCK_UDP) || defined(MODULE_LWIP_SOCK_IP) */
ssize_t lwip_sock_send(struct netconn **conn, const void *data, size_t len,
int proto, const struct _sock_tl_ep *remote, int type)
@ -494,15 +519,20 @@ ssize_t lwip_sock_send(struct netconn **conn, const void *data, size_t len,
netbuf_delete(buf);
return -ENOTCONN;
}
res = len; /* set for non-TCP calls */
if (remote != NULL) {
err = netconn_sendto(tmp, buf, &remote_addr, remote_port);
}
#if LWIP_TCP
else if (tmp->type & NETCONN_TCP) {
err = netconn_write_partly(tmp, data, len, 0, (size_t *)(&res));
}
#endif /* LWIP_TCP */
else {
err = netconn_send(tmp, buf);
}
switch (err) {
case ERR_OK:
res = len;
if (conn != NULL) {
*conn = tmp;
}

View File

@ -0,0 +1,3 @@
MODULE := lwip_sock_tcp
include $(RIOTBASE)/Makefile.base

View File

@ -0,0 +1,376 @@
/*
* Copyright (C) 2016 Freie Universität Berlin
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @{
*
* @file
* @author Martine Lenders <m.lenders@fu-berlin.de>
*/
#include "mutex.h"
#include "net/sock/tcp.h"
#include "timex.h"
#include "lwip/sock_internal.h"
#include "lwip/api.h"
#include "lwip/opt.h"
static inline void _tcp_sock_init(sock_tcp_t *sock, struct netconn *conn,
sock_tcp_queue_t *queue)
{
mutex_init(&sock->mutex);
mutex_lock(&sock->mutex);
netconn_set_noautorecved(conn, 1);
sock->conn = conn;
sock->queue = queue;
sock->last_buf = NULL;
sock->last_offset = 0;
mutex_unlock(&sock->mutex);
}
int sock_tcp_connect(sock_tcp_t *sock, const sock_tcp_ep_t *remote,
uint16_t local_port, uint16_t flags)
{
assert(sock != NULL);
assert((remote != NULL) && (remote->port != 0));
int res;
struct netconn *tmp = NULL;
struct _sock_tl_ep local = { .family = remote->family,
.netif = remote->netif,
.port = local_port };
if ((res = lwip_sock_create(&tmp, &local, (struct _sock_tl_ep *)remote, 0,
flags, NETCONN_TCP)) == 0) {
_tcp_sock_init(sock, tmp, NULL);
}
return res;
}
int sock_tcp_listen(sock_tcp_queue_t *queue, const sock_tcp_ep_t *local,
sock_tcp_t *queue_array, unsigned queue_len,
uint16_t flags)
{
assert(queue != NULL);
assert((local != NULL) && (local->port != 0));
assert((queue_array != NULL) && (queue_len != 0));
int res;
struct netconn *tmp = NULL;
if (queue_len > USHRT_MAX) {
return -EFAULT;
}
if ((res = lwip_sock_create(&tmp, (struct _sock_tl_ep *)local, NULL, 0,
flags, NETCONN_TCP)) < 0) {
return res;
}
assert(tmp != NULL); /* just in case lwIP is trolling */
mutex_init(&queue->mutex);
mutex_lock(&queue->mutex);
queue->conn = tmp;
queue->array = queue_array;
queue->len = queue_len;
queue->used = 0;
memset(queue->array, 0, sizeof(sock_tcp_t) * queue_len);
mutex_unlock(&queue->mutex);
switch (netconn_listen_with_backlog(queue->conn, queue->len)) {
case ERR_OK:
break;
case ERR_MEM:
return -ENOMEM;
case ERR_USE:
return -EADDRINUSE;
case ERR_VAL:
return -EINVAL;
default:
assert(false); /* should not happen since queue->conn is not closed
* and we have a TCP conn */
break;
}
return 0;
}
void sock_tcp_disconnect(sock_tcp_t *sock)
{
assert(sock != NULL);
mutex_lock(&sock->mutex);
if (sock->conn != NULL) {
netconn_close(sock->conn);
netconn_delete(sock->conn);
sock->conn = NULL;
/* if sock came from a sock_tcp_queue_t: since sock is a pointer in it's
* array it is also deleted from there, but we need to decrement the used
* counter */
if (sock->queue != NULL) {
assert(sock->queue->used > 0);
sock->queue->used--;
sock->queue = NULL;
}
}
mutex_unlock(&sock->mutex);
memset(&sock->mutex, 0, sizeof(mutex_t));
}
void sock_tcp_stop_listen(sock_tcp_queue_t *queue)
{
assert(queue != NULL);
mutex_lock(&queue->mutex);
if (queue->conn != NULL) {
netconn_close(queue->conn);
netconn_delete(queue->conn);
queue->conn = NULL;
/* sever connections established through this queue */
for (unsigned i = 0; i < queue->len; i++) {
sock_tcp_disconnect(&queue->array[i]);
}
queue->array = NULL;
queue->len = 0;
queue->used = 0;
}
mutex_unlock(&queue->mutex);
memset(&queue->mutex, 0, sizeof(mutex_t));
}
int sock_tcp_get_local(sock_tcp_t *sock, sock_tcp_ep_t *ep)
{
int res = 0;
assert(sock != NULL);
mutex_lock(&sock->mutex);
if ((sock->conn == NULL) || lwip_sock_get_addr(sock->conn,
(struct _sock_tl_ep *)ep,
1)) {
res = -EADDRNOTAVAIL;
}
mutex_unlock(&sock->mutex);
return res;
}
int sock_tcp_get_remote(sock_tcp_t *sock, sock_tcp_ep_t *ep)
{
int res = 0;
assert(sock != NULL);
mutex_lock(&sock->mutex);
if ((sock->conn == NULL) || lwip_sock_get_addr(sock->conn,
(struct _sock_tl_ep *)ep,
0)) {
res = -ENOTCONN;
}
mutex_unlock(&sock->mutex);
return res;
}
int sock_tcp_queue_get_local(sock_tcp_queue_t *queue, sock_tcp_ep_t *ep)
{
int res = 0;
assert(queue != NULL);
mutex_lock(&queue->mutex);
if ((queue->conn == NULL) || lwip_sock_get_addr(queue->conn,
(struct _sock_tl_ep *)ep,
1)) {
res = -EADDRNOTAVAIL;
}
mutex_unlock(&queue->mutex);
return res;
}
int sock_tcp_accept(sock_tcp_queue_t *queue, sock_tcp_t **sock,
uint32_t timeout)
{
struct netconn *tmp = NULL;
int res = 0;
assert((queue != NULL) && (sock != NULL));
if (queue->conn == NULL) {
return -EINVAL;
}
if (timeout == 0) {
if (!mutex_trylock(&queue->mutex)) {
return -EAGAIN;
}
}
else if (timeout != 0) {
mutex_lock(&queue->mutex);
}
if (queue->used < queue->len) {
#if LWIP_SO_RCVTIMEO
if ((timeout != 0) && (timeout != SOCK_NO_TIMEOUT)) {
netconn_set_recvtimeout(queue->conn, timeout / US_PER_MS);
}
else
#endif
if ((timeout == 0) && !cib_avail(&queue->conn->acceptmbox.mbox.cib)) {
mutex_unlock(&queue->mutex);
return -EAGAIN;
}
switch (netconn_accept(queue->conn, &tmp)) {
case ERR_OK:
for (unsigned short i = 0; i < queue->len; i++) {
sock_tcp_t *s = &queue->array[i];
if (s->conn == NULL) {
_tcp_sock_init(s, tmp, queue);
queue->used++;
assert(queue->used > 0);
*sock = s;
break;
}
}
break;
case ERR_ABRT:
res = -ECONNABORTED;
break;
case ERR_MEM:
res = -ENOMEM;
break;
#if LWIP_SO_RCVTIMEO
case ERR_TIMEOUT:
res = -ETIMEDOUT;
break;
#endif
default:
assert(false);
res = -1;
break;
}
}
else {
res = -ENOMEM;
}
#if LWIP_SO_RCVTIMEO
netconn_set_recvtimeout(queue->conn, 0);
#endif
mutex_unlock(&queue->mutex);
return res;
}
ssize_t sock_tcp_read(sock_tcp_t *sock, void *data, size_t max_len,
uint32_t timeout)
{
uint8_t *data_ptr = data;
struct pbuf *buf;
ssize_t offset = 0, res = 0;
bool done = false;
assert((sock != NULL) && (data != NULL) && (max_len > 0));
if (sock->conn == NULL) {
return -ENOTCONN;
}
if (timeout == 0) {
if (!mutex_trylock(&sock->mutex)) {
return -EAGAIN;
}
}
else {
mutex_lock(&sock->mutex);
}
#if LWIP_SO_RCVTIMEO
if ((timeout != 0) && (timeout != SOCK_NO_TIMEOUT)) {
netconn_set_recvtimeout(sock->conn, timeout / US_PER_MS);
}
else
#endif
if ((timeout == 0) && !cib_avail(&sock->conn->recvmbox.mbox.cib)) {
mutex_unlock(&sock->mutex);
return -EAGAIN;
}
while (!done) {
uint16_t copylen, buf_len;
if (sock->last_buf != NULL) {
buf = sock->last_buf;
}
else {
err_t err;
if ((err = netconn_recv_tcp_pbuf(sock->conn, &buf)) < 0) {
switch (err) {
case ERR_ABRT:
res = -ECONNABORTED;
break;
case ERR_CONN:
res = -EADDRNOTAVAIL;
break;
case ERR_RST:
case ERR_CLSD:
res = -ECONNRESET;
break;
case ERR_MEM:
res = -ENOMEM;
break;
#if LWIP_SO_RCVTIMEO
case ERR_TIMEOUT:
res = -ETIMEDOUT;
break;
#endif
default:
/* no applicable error */
res = -1;
break;
}
break;
}
sock->last_buf = buf;
}
buf_len = buf->tot_len - sock->last_offset;
copylen = (buf_len > max_len) ? (uint16_t)max_len : buf_len;
pbuf_copy_partial(buf, data_ptr + offset, copylen, sock->last_offset);
offset += copylen;
max_len -= copylen; /* should be 0 at minimum due to copylen setting above */
if (max_len == 0) {
done = true;
res = offset; /* in case offset == 0 */
}
/* post-process buf */
if (buf_len > copylen) {
/* there is still data in the buffer */
sock->last_buf = buf;
sock->last_offset = copylen;
}
else {
sock->last_buf = NULL;
sock->last_offset = 0;
pbuf_free(buf);
break;
}
}
if (offset > 0) {
/* inform lwIP how much we receive*/
netconn_recved(sock->conn, (u32_t)offset);
res = offset; /* we received data so return it */
}
/* unset flags */
#if LWIP_SO_RCVTIMEO
netconn_set_recvtimeout(sock->conn, 0);
#endif
netconn_set_nonblocking(sock->conn, false);
mutex_unlock(&sock->mutex);
return res;
}
ssize_t sock_tcp_write(sock_tcp_t *sock, const void *data, size_t len)
{
struct netconn *conn;
int res = 0;
assert(sock != NULL);
assert((len == 0) || (data != NULL)); /* (len != 0) => (data != NULL) */
mutex_lock(&sock->mutex);
if (sock->conn == NULL) {
mutex_unlock(&sock->mutex);
return -ENOTCONN;
}
conn = sock->conn;
mutex_unlock(&sock->mutex); /* we won't change anything to sock here
(lwip_sock_send neither, since it remote is
NULL) so we can leave the mutex */
res = lwip_sock_send(&conn, data, len, 0, NULL, NETCONN_TCP);
return res;
}
/** @} */

View File

@ -34,6 +34,14 @@
extern "C" {
#endif
/**
* @brief Configures @ref sock_tcp_accept() timeout in milliseconds
* (0 by default, which means no timeout)
*/
#ifndef LWIP_SOCK_TCP_ACCEPT_TIMEOUT
#define LWIP_SOCK_TCP_ACCEPT_TIMEOUT (0)
#endif
/**
* @brief Internal helper functions for lwIP
* @internal
@ -44,7 +52,9 @@ int lwip_sock_create(struct netconn **conn, const struct _sock_tl_ep *local,
uint16_t flags, int type);
uint16_t lwip_sock_bind_addr_to_netif(const ip_addr_t *bind_addr);
int lwip_sock_get_addr(struct netconn *conn, struct _sock_tl_ep *ep, u8_t local);
#if defined(MODULE_LWIP_SOCK_UDP) || defined(MODULE_LWIP_SOCK_IP)
int lwip_sock_recv(struct netconn *conn, uint32_t timeout, struct netbuf **buf);
#endif
ssize_t lwip_sock_send(struct netconn **conn, const void *data, size_t len,
int proto, const struct _sock_tl_ep *remote, int type);
/**

View File

@ -33,6 +33,29 @@ struct sock_ip {
struct netconn *conn;
};
/**
* @brief TCP sock type
* @internal
*/
struct sock_tcp {
struct netconn *conn;
struct sock_tcp_queue *queue;
mutex_t mutex;
struct pbuf *last_buf;
ssize_t last_offset;
};
/**
* @brief TCP queue type
*/
struct sock_tcp_queue {
struct netconn *conn;
struct sock_tcp *array;
mutex_t mutex;
unsigned short len;
unsigned short used;
};
/**
* @brief UDP sock type
* @internal

View File

@ -0,0 +1,49 @@
APPLICATION = lwip_sock_tcp
include ../Makefile.tests_common
# lwIP's memory management doesn't seem to work on non 32-bit platforms at the
# moment.
BOARD_BLACKLIST := arduino-uno arduino-duemilanove arduino-mega2560 chronos \
msb-430 msb-430h telosb waspmote-pro wsn430-v1_3b \
wsn430-v1_4 z1
BOARD_INSUFFICIENT_MEMORY = nucleo-f030 nucleo32-f042 nucleo-f334 \
stm32f0discovery weio
LWIP_IPV4 ?= 0
ifneq (0, $(LWIP_IPV4))
USEMODULE += ipv4_addr
USEMODULE += lwip_arp
USEMODULE += lwip_ipv4
CFLAGS += -DETHARP_SUPPORT_STATIC_ENTRIES=1
LWIP_IPV6 ?= 0
else
LWIP_IPV6 ?= 1
endif
ifneq (0, $(LWIP_IPV6))
USEMODULE += ipv6_addr
USEMODULE += lwip_ipv6_autoconfig
endif
USEMODULE += inet_csum
USEMODULE += lwip_ethernet lwip_netdev2
USEMODULE += lwip_sock_tcp
USEMODULE += netdev2_eth
USEMODULE += netdev2_test
USEMODULE += ps
DISABLE_MODULE += auto_init
CFLAGS += -DDEVELHELP
CFLAGS += -DSO_REUSE
CFLAGS += -DLWIP_SO_RCVTIMEO
CFLAGS += -DLWIP_SOCK_TCP_ACCEPT_TIMEOUT=500
CFLAGS += -DLWIP_NETIF_LOOPBACK=1
CFLAGS += -DLWIP_HAVE_LOOPIF=1
include $(RIOTBASE)/Makefile.include
test:
./tests/01-run.py

View File

@ -0,0 +1,33 @@
Tests for lwIP's sock_tcp port
==============================
This tests the `sock_tcp` port of lwIP. There is no network device needed since
a [virtual device](http://doc.riot-os.org/group__sys__netdev2__test.html) is
provided at the backend.
These tests test both IPv4 and IPv6 capabilities. They can be activated by
the `LWIP_IPV4` and `LWIP_IPV6` environment variables to a non-zero value.
IPv6 is activated by default:
```sh
make all test
# or
LWIP_IPV6=1 make all test
```
To just test IPv4 set the `LWIP_IPV4` to a non-zero value (IPv6 will be
deactivated automatically):
```sh
LWIP_IPV4=1 make all test
```
To test both set the `LWIP_IPV4` and `LWIP_IPV6` to a non-zero value:
```sh
LWIP_IPV4=1 LWIP_IPV6=1 make all test
```
Since lwIP uses a lot of macro magic to activate/deactivate these capabilities
it is advisable to **test all three configurations individually** (just IPv4,
just IPv6, IPv4/IPv6 dual stack mode).

View File

@ -0,0 +1,49 @@
/*
* Copyright (C) 2016 Freie Universität Berlin
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @defgroup
* @ingroup
* @brief
* @{
*
* @file
* @brief
*
* @author Martine Lenders <m.lenders@fu-berlin.de>
*/
#ifndef CONSTANTS_H_
#define CONSTANTS_H_
#ifdef __cplusplus
extern "C" {
#endif
#define _TEST_PORT_LOCAL (0x2c94)
#define _TEST_PORT_REMOTE (0xa615)
#define _TEST_NETIF (1)
#define _TEST_TIMEOUT (1000000U)
#define _TEST_ADDR4_LOCAL (0xc0a84f96U) /* 192.168.79.150 */
#define _TEST_ADDR4_REMOTE (0x7f000001U) /* 127.0.0.1 */
#define _TEST_ADDR4_WRONG (0x254c6b4cU)
#define _TEST_ADDR4_MASK (0xffffff00U) /* 255.255.255.0 */
#define _TEST_ADDR4_GW (0UL) /* so we can test unreachability */
#define _TEST_ADDR6_LOCAL { 0x2f, 0xc4, 0x11, 0x5a, 0xe6, 0x91, 0x8d, 0x5d, \
0x8c, 0xd1, 0x47, 0x07, 0xb7, 0x6f, 0x9b, 0x48 }
#define _TEST_ADDR6_REMOTE { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }
#define _TEST_ADDR6_WRONG { 0x2a, 0xce, 0x5d, 0x4e, 0xc8, 0xbf, 0x86, 0xf7, \
0x85, 0x49, 0xb4, 0x19, 0xf2, 0x28, 0xde, 0x9b }
#ifdef __cplusplus
}
#endif
#endif /* CONSTANTS_H_ */
/** @} */

1192
tests/lwip_sock_tcp/main.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,30 @@
/*
* Copyright (C) 2016 Freie Universität Berlin
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @{
*
* @file
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
*/
#include "xtimer.h"
#include "lwip.h"
#include "lwip/netif.h"
#include "stack.h"
void _net_init(void)
{
xtimer_init();
lwip_bootstrap();
}
/** @} */

View File

@ -0,0 +1,37 @@
/*
* Copyright (C) 2016 Freie Universität Berlin
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @defgroup
* @ingroup
* @brief
* @{
*
* @file
* @brief
*
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
*/
#ifndef STACK_H_
#define STACK_H_
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Initializes networking for tests
*/
void _net_init(void);
#ifdef __cplusplus
}
#endif
#endif /* STACK_H_ */
/** @} */

View File

@ -0,0 +1,141 @@
#!/usr/bin/env python3
# Copyright (C) 2016 Freie Universität Berlin
#
# This file is subject to the terms and conditions of the GNU Lesser
# General Public License v2.1. See the file LICENSE in the top level
# directory for more details.
import os
import sys
from datetime import datetime
sys.path.append(os.path.join(os.environ['RIOTBASE'], 'dist/tools/testrunner'))
import testrunner
class InvalidTimeout(Exception):
pass
def _reuse_tests(code):
return code & 1
def _ipv6_tests(code):
return code & (1 << 6)
def _ipv4_tests(code):
return code & (1 << 4)
def testfunc(child):
child.expect(u"code (0x[0-9a-f]{2})")
code = int(child.match.group(1), base=16)
if _ipv4_tests(code):
if _reuse_tests(code):
child.expect_exact("Calling test_tcp_connect4__EADDRINUSE()")
child.expect_exact("Calling test_tcp_connect4__EAFNOSUPPORT()")
child.expect_exact("Calling test_tcp_connect4__EINVAL_addr()")
child.expect_exact("Calling test_tcp_connect4__EINVAL_netif()")
child.expect_exact("Calling test_tcp_connect4__success_without_port()")
child.expect_exact("Calling test_tcp_connect4__success_local_port()")
if _reuse_tests(code):
child.expect_exact("Calling test_tcp_listen4__EADDRINUSE()")
child.expect_exact("Calling test_tcp_listen4__EAFNOSUPPORT()")
child.expect_exact("Calling test_tcp_listen4__EINVAL()")
child.expect_exact("Calling test_tcp_listen4__success_any_netif()")
child.expect_exact("Calling test_tcp_listen4__success_spec_netif()")
child.expect_exact("Calling test_tcp_accept4__EAGAIN()")
child.expect_exact("Calling test_tcp_accept4__EINVAL()")
child.expect_exact("Calling test_tcp_accept4__ETIMEDOUT()")
start = datetime.now()
child.expect_exact(" * Calling sock_tcp_accept()")
child.expect(u" \\* \\(timed out with timeout (\\d+)\\)")
exp_diff = int(child.match.group(1))
stop = datetime.now()
diff = (stop - start)
diff = (diff.seconds * 1000000) + diff.microseconds
# fail within 5% of expected
if diff > (exp_diff + (exp_diff * 0.05)) or \
diff < (exp_diff - (exp_diff * 0.05)):
raise InvalidTimeout("Invalid timeout %d (expected %d)" % (diff, exp_diff));
else:
print("Timed out correctly: %d (expected %d)" % (diff, exp_diff))
child.expect_exact("Calling test_tcp_accept4__success()")
child.expect_exact("Calling test_tcp_read4__EAGAIN()")
child.expect_exact("Calling test_tcp_read4__ECONNRESET()")
child.expect_exact("Calling test_tcp_read4__ENOTCONN()")
child.expect_exact("Calling test_tcp_read4__ETIMEDOUT()")
start = datetime.now()
child.expect_exact(" * Calling sock_tcp_read()")
child.expect(u" \\* \\(timed out with timeout (\\d+)\\)")
exp_diff = int(child.match.group(1))
stop = datetime.now()
diff = (stop - start)
diff = (diff.seconds * 1000000) + diff.microseconds
# fail within 5% of expected
if diff > (exp_diff + (exp_diff * 0.05)) or \
diff < (exp_diff - (exp_diff * 0.05)):
raise InvalidTimeout("Invalid timeout %d (expected %d)" % (diff, exp_diff));
else:
print("Timed out correctly: %d (expected %d)" % (diff, exp_diff))
child.expect_exact("Calling test_tcp_read4__success()")
child.expect_exact("Calling test_tcp_read4__success_with_timeout()")
child.expect_exact("Calling test_tcp_read4__success_non_blocking()")
child.expect_exact("Calling test_tcp_write4__ENOTCONN()")
child.expect_exact("Calling test_tcp_write4__success()")
if _ipv6_tests(code):
if _reuse_tests(code):
child.expect_exact("Calling test_tcp_connect6__EADDRINUSE()")
child.expect_exact("Calling test_tcp_connect6__EAFNOSUPPORT()")
child.expect_exact("Calling test_tcp_connect6__EINVAL_addr()")
child.expect_exact("Calling test_tcp_connect6__EINVAL_netif()")
child.expect_exact("Calling test_tcp_connect6__success_without_port()")
child.expect_exact("Calling test_tcp_connect6__success_local_port()")
if _reuse_tests(code):
child.expect_exact("Calling test_tcp_listen6__EADDRINUSE()")
child.expect_exact("Calling test_tcp_listen6__EAFNOSUPPORT()")
child.expect_exact("Calling test_tcp_listen6__EINVAL()")
child.expect_exact("Calling test_tcp_listen6__success_any_netif()")
child.expect_exact("Calling test_tcp_listen6__success_spec_netif()")
child.expect_exact("Calling test_tcp_accept6__EAGAIN()")
child.expect_exact("Calling test_tcp_accept6__EINVAL()")
child.expect_exact("Calling test_tcp_accept6__ETIMEDOUT()")
start = datetime.now()
child.expect_exact(" * Calling sock_tcp_accept()")
child.expect(u" \\* \\(timed out with timeout (\\d+)\\)")
exp_diff = int(child.match.group(1))
stop = datetime.now()
diff = (stop - start)
diff = (diff.seconds * 1000000) + diff.microseconds
# fail within 5% of expected
if diff > (exp_diff + (exp_diff * 0.05)) or \
diff < (exp_diff - (exp_diff * 0.05)):
raise InvalidTimeout("Invalid timeout %d (expected %d)" % (diff, exp_diff));
else:
print("Timed out correctly: %d (expected %d)" % (diff, exp_diff))
child.expect_exact("Calling test_tcp_accept6__success()")
child.expect_exact("Calling test_tcp_read6__EAGAIN()")
child.expect_exact("Calling test_tcp_read6__ECONNRESET()")
child.expect_exact("Calling test_tcp_read6__ENOTCONN()")
child.expect_exact("Calling test_tcp_read6__ETIMEDOUT()")
start = datetime.now()
child.expect_exact(" * Calling sock_tcp_read()")
child.expect(u" \\* \\(timed out with timeout (\\d+)\\)")
exp_diff = int(child.match.group(1))
stop = datetime.now()
diff = (stop - start)
diff = (diff.seconds * 1000000) + diff.microseconds
# fail within 5% of expected
if diff > (exp_diff + (exp_diff * 0.05)) or \
diff < (exp_diff - (exp_diff * 0.05)):
raise InvalidTimeout("Invalid timeout %d (expected %d)" % (diff, exp_diff));
else:
print("Timed out correctly: %d (expected %d)" % (diff, exp_diff))
child.expect_exact("Calling test_tcp_read6__success()")
child.expect_exact("Calling test_tcp_read6__success_with_timeout()")
child.expect_exact("Calling test_tcp_read6__success_non_blocking()")
child.expect_exact("Calling test_tcp_write6__ENOTCONN()")
child.expect_exact("Calling test_tcp_write6__success()")
child.expect_exact(u"ALL TESTS SUCCESSFUL")
if __name__ == "__main__":
sys.exit(testrunner.run(testfunc, timeout=60))