2016-02-04 14:37:35 +01:00
|
|
|
/*
|
2017-02-06 18:26:45 +01:00
|
|
|
* Copyright (C) 2015-2017 Simon Brummer
|
2016-02-04 14:37:35 +01:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
2017-02-20 21:42:59 +01:00
|
|
|
|
2016-02-04 14:37:35 +01:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include "thread.h"
|
|
|
|
#include "net/af.h"
|
|
|
|
#include "net/gnrc/ipv6.h"
|
|
|
|
#include "net/gnrc/tcp.h"
|
|
|
|
|
|
|
|
#define ENABLE_DEBUG (0)
|
|
|
|
#include "debug.h"
|
|
|
|
|
|
|
|
/* Number of possible parallel connections */
|
|
|
|
#ifndef CONNS
|
2017-02-04 10:19:59 +01:00
|
|
|
#define CONNS (1)
|
2016-02-04 14:37:35 +01:00
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Amount of data to transmit */
|
|
|
|
#ifndef NBYTE
|
|
|
|
#define NBYTE (2048)
|
|
|
|
#endif
|
|
|
|
|
2017-03-06 08:47:06 +01:00
|
|
|
/* Test pattern used by client application */
|
2016-02-04 14:37:35 +01:00
|
|
|
#ifndef TEST_PATERN_CLI
|
|
|
|
#define TEST_PATERN_CLI (0xF0)
|
|
|
|
#endif
|
|
|
|
|
2017-03-06 08:47:06 +01:00
|
|
|
/* Test pattern used by server application */
|
2016-02-04 14:37:35 +01:00
|
|
|
#ifndef TEST_PATERN_SRV
|
|
|
|
#define TEST_PATERN_SRV (0xA7)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
uint8_t bufs[CONNS][NBYTE];
|
|
|
|
uint8_t stacks[CONNS][THREAD_STACKSIZE_DEFAULT + THREAD_EXTRA_STACKSIZE_PRINTF];
|
|
|
|
|
2017-03-06 08:47:06 +01:00
|
|
|
/* "ifconfig" shell command */
|
2016-02-04 14:37:35 +01:00
|
|
|
extern int _netif_config(int argc, char **argv);
|
|
|
|
|
2017-03-06 08:47:06 +01:00
|
|
|
/* Server thread */
|
2016-02-04 14:37:35 +01:00
|
|
|
void *srv_thread(void *arg);
|
|
|
|
|
|
|
|
int main(void)
|
|
|
|
{
|
2017-03-06 08:47:06 +01:00
|
|
|
/* Get PID of the a network interface */
|
|
|
|
kernel_pid_t ifs[GNRC_NETIF_NUMOF];
|
|
|
|
size_t numof = gnrc_netif_get(ifs);
|
|
|
|
if (10 <= numof) {
|
|
|
|
printf("No valid network interface found\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set pre-configured IP address */
|
|
|
|
char if_pid[] = {ifs[0] + '0', '\0'};
|
|
|
|
char *cmd[] = {"ifconfig", if_pid, "add", "unicast", LOCAL_ADDR};
|
|
|
|
_netif_config(5, cmd);
|
2016-02-04 14:37:35 +01:00
|
|
|
|
2017-03-06 08:47:06 +01:00
|
|
|
/* Test configuration */
|
|
|
|
printf("\nStarting server: LOCAL_ADDR=%s, LOCAL_PORT=%d, ", LOCAL_ADDR, LOCAL_PORT);
|
|
|
|
printf("CONNS=%d, NBYTE=%d, CYCLES=%d\n\n", CONNS, NBYTE, CYCLES);
|
2016-02-04 14:37:35 +01:00
|
|
|
|
2017-03-06 08:47:06 +01:00
|
|
|
/* Start Threads to handle connections */
|
2016-02-04 14:37:35 +01:00
|
|
|
for (int i = 0; i < CONNS; i += 1) {
|
2017-02-04 10:19:59 +01:00
|
|
|
thread_create((char *) stacks[i], sizeof(stacks[i]), THREAD_PRIORITY_MAIN, 0, srv_thread,
|
|
|
|
(void *) i, NULL);
|
2016-02-04 14:37:35 +01:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void *srv_thread(void *arg)
|
|
|
|
{
|
2017-02-04 10:19:59 +01:00
|
|
|
int tid = (int) arg;
|
2016-02-04 14:37:35 +01:00
|
|
|
uint32_t cycles = 0;
|
|
|
|
uint32_t cycles_ok = 0;
|
|
|
|
uint32_t failed_payload_verifications = 0;
|
|
|
|
|
|
|
|
/* Transmission control block */
|
|
|
|
gnrc_tcp_tcb_t tcb;
|
|
|
|
|
|
|
|
/* Connection handling code */
|
|
|
|
printf("Server running: TID=%d\n", tid);
|
2017-03-06 08:47:06 +01:00
|
|
|
while (cycles < CYCLES) {
|
|
|
|
/* Initialize TCB struct */
|
2016-02-04 14:37:35 +01:00
|
|
|
gnrc_tcp_tcb_init(&tcb);
|
|
|
|
|
2017-03-06 08:47:06 +01:00
|
|
|
/* Connect to peer */
|
2016-02-04 14:37:35 +01:00
|
|
|
int ret = gnrc_tcp_open_passive(&tcb, AF_INET6, NULL, LOCAL_PORT);
|
|
|
|
switch (ret) {
|
|
|
|
case 0:
|
|
|
|
DEBUG("TID=%d : gnrc_tcp_open_passive() : 0 : ok\n", tid);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case -EISCONN:
|
|
|
|
printf("TID=%d : gnrc_tcp_open_passive() : -EISCONN\n", tid);
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
case -EINVAL:
|
|
|
|
printf("TID=%d : gnrc_tcp_open_passive() : -EINVAL\n", tid);
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
case -EAFNOSUPPORT:
|
|
|
|
printf("TID=%d : gnrc_tcp_open_passive() : -EAFNOSUPPORT\n", tid);
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
case -ENOMEM:
|
|
|
|
printf("TID=%d : gnrc_tcp_open_passive() : -ENOMEM\n", tid);
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
default:
|
|
|
|
printf("TID=%d : gnrc_tcp_open_passive() : %d\n", tid, ret);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-03-06 08:47:06 +01:00
|
|
|
/* Receive data, stop if errors were found */
|
2016-02-04 14:37:35 +01:00
|
|
|
for (size_t rcvd = 0; rcvd < sizeof(bufs[tid]) && ret >= 0; rcvd += ret) {
|
2017-02-04 10:19:59 +01:00
|
|
|
ret = gnrc_tcp_recv(&tcb, (void *) (bufs[tid] + rcvd), sizeof(bufs[tid]) - rcvd,
|
2016-02-04 14:37:35 +01:00
|
|
|
GNRC_TCP_CONNECTION_TIMEOUT_DURATION);
|
|
|
|
switch (ret) {
|
|
|
|
case -ENOTCONN:
|
|
|
|
printf("TID=%d : gnrc_tcp_rcvd() : -ENOTCONN\n", tid);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case -EAGAIN:
|
|
|
|
printf("TID=%d : gnrc_tcp_rcvd() : -EAGAIN : retry after 10sec\n", tid);
|
|
|
|
ret = 0;
|
|
|
|
xtimer_sleep(10);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case -ECONNABORTED:
|
|
|
|
printf("TID=%d : gnrc_tcp_rcvd() : -ECONNABORTED\n", tid);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case -ECONNRESET:
|
|
|
|
printf("TID=%d : gnrc_tcp_rcvd() : -ECONNRESET\n", tid);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case -ETIMEDOUT:
|
|
|
|
printf("TID=%d : gnrc_tcp_rcvd() : -ETIMEDOUT\n", tid);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
if (ret >= 0) {
|
|
|
|
DEBUG("TID=%d : gnrc_tcp_rcvd() : %d Bytes read\n", tid, ret);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
printf("TID=%d : gnrc_tcp_rcvd() : %d\n", tid, ret);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check received pattern */
|
2017-02-04 10:19:59 +01:00
|
|
|
for (size_t i = 0; i < sizeof(bufs[tid]); ++i) {
|
2016-02-04 14:37:35 +01:00
|
|
|
if (bufs[tid][i] != TEST_PATERN_CLI) {
|
|
|
|
printf("TID=%d : Payload verfication failed\n", tid);
|
|
|
|
failed_payload_verifications += 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-06 08:47:06 +01:00
|
|
|
/* Fill buffer with a test pattern */
|
2017-02-04 10:19:59 +01:00
|
|
|
for (size_t i = 0; i < sizeof(bufs[tid]); ++i) {
|
2016-02-04 14:37:35 +01:00
|
|
|
bufs[tid][i] = TEST_PATERN_SRV;
|
|
|
|
}
|
|
|
|
|
2017-03-06 08:47:06 +01:00
|
|
|
/* Send data, stop if errors were found */
|
2016-02-04 14:37:35 +01:00
|
|
|
for (size_t sent = 0; sent < sizeof(bufs[tid]) && ret >= 0; sent += ret) {
|
|
|
|
ret = gnrc_tcp_send(&tcb, bufs[tid] + sent, sizeof(bufs[tid]) - sent, 0);
|
|
|
|
switch (ret) {
|
|
|
|
case -ENOTCONN:
|
|
|
|
printf("TID=%d : gnrc_tcp_send() : -ENOTCONN\n", tid);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case -ECONNABORTED:
|
|
|
|
printf("TID=%d : gnrc_tcp_send() : -ECONNABORTED\n", tid);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case -ETIMEDOUT:
|
|
|
|
printf("TID=%d : gnrc_tcp_send() : -ETIMEDOUT\n", tid);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case -ECONNRESET:
|
|
|
|
printf("TID=%d : gnrc_tcp_send() : -ECONNRESET\n", tid);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
if (ret >= 0) {
|
|
|
|
DEBUG("TID=%d : gnrc_tcp_send() : %d Bytes sent.\n", tid, ret);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
printf("TID=%d : gnrc_tcp_send() : %d\n", tid, ret);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-06 08:47:06 +01:00
|
|
|
/* Close connection */
|
2016-02-04 14:37:35 +01:00
|
|
|
gnrc_tcp_close(&tcb);
|
|
|
|
|
2017-03-06 08:47:06 +01:00
|
|
|
/* Gather data */
|
2016-02-04 14:37:35 +01:00
|
|
|
cycles += 1;
|
2017-02-04 10:19:59 +01:00
|
|
|
if (ret >= 0) {
|
2016-02-04 14:37:35 +01:00
|
|
|
cycles_ok += 1;
|
|
|
|
}
|
|
|
|
printf("TID=%d : %"PRIi32" test cycles completed. %"PRIi32" ok, %"PRIi32" faulty",
|
|
|
|
tid, cycles, cycles_ok, cycles - cycles_ok);
|
|
|
|
printf(", %"PRIi32" failed payload verifications\n", failed_payload_verifications);
|
|
|
|
}
|
2017-03-06 08:47:06 +01:00
|
|
|
printf("server thread terminating: TID=%d\n", tid);
|
2016-02-04 14:37:35 +01:00
|
|
|
return 0;
|
|
|
|
}
|