Porting PicoTCP WIP
This commit is contained in:
36
kernel/picotcp/test/examples/Makefile
Normal file
36
kernel/picotcp/test/examples/Makefile
Normal file
@ -0,0 +1,36 @@
|
||||
PREFIX?=../../build
|
||||
CFLAGS+=-I../../include/ -I../../modules -I../../build/include -I . -ggdb
|
||||
|
||||
|
||||
$(PREFIX)/examples/%.o: %.c
|
||||
@mkdir -p $(PREFIX)/examples
|
||||
@echo -e "\t[CC] $@"
|
||||
@$(CC) -c $(CFLAGS) -o $@ $<
|
||||
|
||||
OBJS:= \
|
||||
$(PREFIX)/examples/dhcp_client.o \
|
||||
$(PREFIX)/examples/dhcp_server.o \
|
||||
$(PREFIX)/examples/dns_sd.o \
|
||||
$(PREFIX)/examples/dnsclient.o \
|
||||
$(PREFIX)/examples/mdns.o \
|
||||
$(PREFIX)/examples/multicast_recv.o \
|
||||
$(PREFIX)/examples/multicast_ip6_recv.o \
|
||||
$(PREFIX)/examples/multicast_send.o \
|
||||
$(PREFIX)/examples/multicast_ip6_send.o \
|
||||
$(PREFIX)/examples/natbox.o \
|
||||
$(PREFIX)/examples/noop.o \
|
||||
$(PREFIX)/examples/ping.o \
|
||||
$(PREFIX)/examples/slaacv4.o \
|
||||
$(PREFIX)/examples/sntp.o \
|
||||
$(PREFIX)/examples/tcpbench.o \
|
||||
$(PREFIX)/examples/tcpclient.o \
|
||||
$(PREFIX)/examples/tcpecho.o \
|
||||
$(PREFIX)/examples/tftp.o \
|
||||
$(PREFIX)/examples/udp_client.o \
|
||||
$(PREFIX)/examples/udp_echo.o \
|
||||
$(PREFIX)/examples/udpnat.o \
|
||||
$(PREFIX)/examples/udp_sendto_test.o \
|
||||
$(PREFIX)/examples/iperfc.o \
|
||||
|
||||
|
||||
all: $(OBJS)
|
||||
114
kernel/picotcp/test/examples/dhcp_client.c
Normal file
114
kernel/picotcp/test/examples/dhcp_client.c
Normal file
@ -0,0 +1,114 @@
|
||||
#include "utils.h"
|
||||
#include <pico_ipv4.h>
|
||||
#include <pico_dhcp_client.h>
|
||||
#include <pico_socket.h>
|
||||
#include <pico_icmp4.h>
|
||||
#include <pico_device.h>
|
||||
/*** START DHCP Client ***/
|
||||
#ifdef PICO_SUPPORT_DHCPC
|
||||
|
||||
/* This must stay global, its lifetime is the same as the dhcp negotiation */
|
||||
uint32_t dhcpclient_xid;
|
||||
|
||||
|
||||
static uint8_t dhcpclient_devices = 0;
|
||||
|
||||
void ping_callback_dhcpclient(struct pico_icmp4_stats *s)
|
||||
{
|
||||
char host[30] = { };
|
||||
|
||||
pico_ipv4_to_string(host, s->dst.addr);
|
||||
if (s->err == 0) {
|
||||
dbg("DHCP client: %lu bytes from %s: icmp_req=%lu ttl=64 time=%lu ms\n",
|
||||
s->size, host, s->seq, (long unsigned int)s->time);
|
||||
if (s->seq >= 3) {
|
||||
dbg("DHCP client: TEST SUCCESS!\n");
|
||||
if (--dhcpclient_devices <= 0)
|
||||
exit(0);
|
||||
}
|
||||
} else {
|
||||
dbg("DHCP client: ping %lu to %s error %d\n", s->seq, host, s->err);
|
||||
dbg("DHCP client: TEST FAILED!\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void callback_dhcpclient(void *arg, int code)
|
||||
{
|
||||
struct pico_ip4 address = ZERO_IP4, gateway = ZERO_IP4;
|
||||
char s_address[16] = { }, s_gateway[16] = { };
|
||||
|
||||
printf("DHCP client: callback happened with code %d!\n", code);
|
||||
if (code == PICO_DHCP_SUCCESS) {
|
||||
address = pico_dhcp_get_address(arg);
|
||||
gateway = pico_dhcp_get_gateway(arg);
|
||||
pico_ipv4_to_string(s_address, address.addr);
|
||||
pico_ipv4_to_string(s_gateway, gateway.addr);
|
||||
printf("DHCP client: got IP %s assigned with cli %p\n", s_address, arg);
|
||||
#ifdef PICO_SUPPORT_PING
|
||||
pico_icmp4_ping(s_gateway, 3, 1000, 5000, 32, ping_callback_dhcpclient);
|
||||
/* optional test to check routing when links get added and deleted */
|
||||
/* do {
|
||||
char *new_arg = NULL, *p = NULL;
|
||||
new_arg = calloc(1, strlen(s_address) + strlen(":224.7.7.7:6667:6667") + 1);
|
||||
p = strcat(new_arg, s_address);
|
||||
p = strcat(p + strlen(s_address), ":224.7.7.7:6667:6667");
|
||||
app_mcastsend(new_arg);
|
||||
} while (0);
|
||||
*/
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void app_dhcp_client(char *arg)
|
||||
{
|
||||
char *sdev = NULL;
|
||||
char *nxt = arg;
|
||||
struct pico_device *dev = NULL;
|
||||
|
||||
if (!nxt)
|
||||
goto out;
|
||||
|
||||
while (nxt) {
|
||||
if (nxt) {
|
||||
nxt = cpy_arg(&sdev, nxt);
|
||||
if(!sdev) {
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
dev = pico_get_device(sdev);
|
||||
if(dev == NULL) {
|
||||
if (sdev)
|
||||
free(sdev);
|
||||
|
||||
printf("%s: error getting device %s: %s\n", __FUNCTION__, dev->name, strerror(pico_err));
|
||||
exit(255);
|
||||
}
|
||||
|
||||
printf("Starting negotiation\n");
|
||||
|
||||
if (pico_dhcp_initiate_negotiation(dev, &callback_dhcpclient, &dhcpclient_xid) < 0) {
|
||||
printf("%s: error initiating negotiation: %s\n", __FUNCTION__, strerror(pico_err));
|
||||
if (sdev)
|
||||
free(sdev);
|
||||
|
||||
exit(255);
|
||||
}
|
||||
|
||||
if (sdev)
|
||||
free(sdev);
|
||||
|
||||
dhcpclient_devices++;
|
||||
}
|
||||
return;
|
||||
|
||||
out:
|
||||
fprintf(stderr, "dhcpclient expects the following format: dhcpclient:dev_name:[dev_name]\n");
|
||||
if (sdev)
|
||||
free(sdev);
|
||||
|
||||
exit(255);
|
||||
}
|
||||
#endif
|
||||
/*** END DHCP Client ***/
|
||||
99
kernel/picotcp/test/examples/dhcp_server.c
Normal file
99
kernel/picotcp/test/examples/dhcp_server.c
Normal file
@ -0,0 +1,99 @@
|
||||
#include "utils.h"
|
||||
#include <pico_ipv4.h>
|
||||
#include <pico_device.h>
|
||||
#include <pico_dhcp_server.h>
|
||||
|
||||
/*** START DHCP Server ***/
|
||||
#ifdef PICO_SUPPORT_DHCPD
|
||||
/* ./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.40.0.1:255.255.0.0: -a dhcpserver:pic0:10.40.0.1:255.255.255.0:64:128
|
||||
* ./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.40.0.10:255.255.255.0: --vde pic1:/tmp/pic1.ctl:10.50.0.10:255.255.255.0: \
|
||||
* -a dhcpserver:pic0:10.40.0.10:255.255.255.0:64:128:pic1:10.50.0.10:255.255.255.0:64:128
|
||||
*/
|
||||
void app_dhcp_server(char *arg)
|
||||
{
|
||||
struct pico_device *dev = NULL;
|
||||
struct pico_dhcp_server_setting s = {
|
||||
0
|
||||
};
|
||||
int pool_start = 0, pool_end = 0;
|
||||
char *s_name = NULL, *s_addr = NULL, *s_netm = NULL, *s_pool_start = NULL, *s_pool_end = NULL;
|
||||
char *nxt = arg;
|
||||
|
||||
if (!nxt)
|
||||
goto out;
|
||||
|
||||
while (nxt) {
|
||||
if (nxt) {
|
||||
nxt = cpy_arg(&s_name, nxt);
|
||||
if (!s_name) {
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (nxt) {
|
||||
nxt = cpy_arg(&s_addr, nxt);
|
||||
if (s_addr) {
|
||||
pico_string_to_ipv4(s_addr, &s.server_ip.addr);
|
||||
} else {
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (nxt) {
|
||||
nxt = cpy_arg(&s_netm, nxt);
|
||||
if (s_netm) {
|
||||
pico_string_to_ipv4(s_netm, &s.netmask.addr);
|
||||
} else {
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (nxt) {
|
||||
nxt = cpy_arg(&s_pool_start, nxt);
|
||||
if (s_pool_start && atoi(s_pool_start)) {
|
||||
pool_start = atoi(s_pool_start);
|
||||
} else {
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (nxt) {
|
||||
nxt = cpy_arg(&s_pool_end, nxt);
|
||||
if (s_pool_end && atoi(s_pool_end)) {
|
||||
pool_end = atoi(s_pool_end);
|
||||
} else {
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
goto out;
|
||||
}
|
||||
|
||||
dev = (struct pico_device *)pico_get_device(s_name);
|
||||
if (dev == NULL) {
|
||||
fprintf(stderr, "No device with name %s found\n", s_name);
|
||||
exit(255);
|
||||
}
|
||||
|
||||
s.dev = dev;
|
||||
s.pool_start = (s.server_ip.addr & s.netmask.addr) | long_be(pool_start);
|
||||
s.pool_end = (s.server_ip.addr & s.netmask.addr) | long_be(pool_end);
|
||||
|
||||
pico_dhcp_server_initiate(&s);
|
||||
}
|
||||
return;
|
||||
|
||||
out:
|
||||
fprintf(stderr, "dhcpserver expects the following format: dhcpserver:dev_name:dev_addr:dev_netm:pool_start:pool_end\n");
|
||||
exit(255);
|
||||
|
||||
}
|
||||
#endif
|
||||
/*** END DHCP Server ***/
|
||||
112
kernel/picotcp/test/examples/dns_sd.c
Normal file
112
kernel/picotcp/test/examples/dns_sd.c
Normal file
@ -0,0 +1,112 @@
|
||||
#include "utils.h"
|
||||
#include <pico_dns_sd.h>
|
||||
#include <pico_ipv4.h>
|
||||
#include <pico_addressing.h>
|
||||
#include <pico_device.h>
|
||||
#include <pico_ipv4.h>
|
||||
|
||||
/*** START DNS_SD ***/
|
||||
#ifdef PICO_SUPPORT_DNS_SD
|
||||
|
||||
#define TTL 30
|
||||
#define SECONDS 10
|
||||
|
||||
static int fully_initialized = 0;
|
||||
static char *service_name = NULL;
|
||||
|
||||
void dns_sd_claimed_callback( pico_mdns_rtree *tree,
|
||||
char *str,
|
||||
void *arg )
|
||||
{
|
||||
printf("DONE - Registering DNS-SD Service\n");
|
||||
|
||||
IGNORE_PARAMETER(tree);
|
||||
IGNORE_PARAMETER(str);
|
||||
IGNORE_PARAMETER(arg);
|
||||
}
|
||||
|
||||
void dns_sd_init_callback( pico_mdns_rtree *tree,
|
||||
char *str,
|
||||
void *arg )
|
||||
{
|
||||
PICO_DNS_SD_KV_VECTOR_DECLARE(key_value_pair_vector);
|
||||
|
||||
IGNORE_PARAMETER(str);
|
||||
IGNORE_PARAMETER(arg);
|
||||
IGNORE_PARAMETER(tree);
|
||||
|
||||
pico_dns_sd_kv_vector_add(&key_value_pair_vector, "key", "value");
|
||||
|
||||
printf("DONE - Initialising DNS Service Discovery module.\n");
|
||||
|
||||
if (pico_dns_sd_register_service(service_name,
|
||||
"_http._tcp", 80,
|
||||
&key_value_pair_vector,
|
||||
TTL, dns_sd_claimed_callback, NULL) < 0) {
|
||||
printf("Registering service failed!\n");
|
||||
}
|
||||
|
||||
fully_initialized = 1;
|
||||
}
|
||||
|
||||
void app_dns_sd(char *arg, struct pico_ip4 address)
|
||||
{
|
||||
char *hostname;
|
||||
char *nxt = arg;
|
||||
uint64_t starttime = 0;
|
||||
int once = 0;
|
||||
|
||||
if (!nxt) {
|
||||
exit(255);
|
||||
}
|
||||
|
||||
nxt = cpy_arg(&hostname, nxt);
|
||||
if(!hostname) {
|
||||
exit(255);
|
||||
}
|
||||
|
||||
if(!nxt) {
|
||||
printf("Not enough args supplied!\n");
|
||||
exit(255);
|
||||
}
|
||||
|
||||
nxt = cpy_arg(&service_name, nxt);
|
||||
if(!service_name) {
|
||||
exit(255);
|
||||
}
|
||||
|
||||
printf("\nStarting DNS Service Discovery module...\n");
|
||||
if (pico_dns_sd_init(hostname, address, &dns_sd_init_callback, NULL) != 0) {
|
||||
printf("Initialisation returned with Error!\n");
|
||||
exit(255);
|
||||
}
|
||||
|
||||
printf("\nTry reinitialising DNS-SD\n");
|
||||
if (pico_dns_sd_init(hostname, address, &dns_sd_init_callback, NULL)) {
|
||||
printf("Initialisation returned with Error!\n");
|
||||
exit(255);
|
||||
}
|
||||
|
||||
printf("DONE - Re-initialising DNS-SD module.\n");
|
||||
|
||||
starttime = PICO_TIME_MS();
|
||||
printf("Starting time: %d\n", starttime);
|
||||
|
||||
while(1) {
|
||||
pico_stack_tick();
|
||||
usleep(2000);
|
||||
|
||||
if (((PICO_TIME_MS() - starttime) > SECONDS * 1000) && fully_initialized && !once) {
|
||||
printf("\nTry reinitialising DNS-SD (a second time)\n");
|
||||
if (pico_dns_sd_init(hostname, address, &dns_sd_init_callback, NULL)) {
|
||||
printf("Initialisation returned with Error!\n");
|
||||
exit(255);
|
||||
}
|
||||
once = 1;
|
||||
printf("DONE - Re-initialising mDNS module. (a second time)\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
/*** END DNS_SD ***/
|
||||
120
kernel/picotcp/test/examples/dnsclient.c
Normal file
120
kernel/picotcp/test/examples/dnsclient.c
Normal file
@ -0,0 +1,120 @@
|
||||
#include <stdint.h>
|
||||
#include <pico_stack.h>
|
||||
#include <pico_ipv4.h>
|
||||
#include <pico_dns_client.h>
|
||||
#include "utils.h"
|
||||
extern int IPV6_MODE;
|
||||
|
||||
/*** START UDP DNS CLIENT ***/
|
||||
/*
|
||||
./test/vde_sock_start.sh
|
||||
echo 1 > /proc/sys/net/ipv4/ip_forward
|
||||
iptables -t nat -A POSTROUTING -o wlan0 -j MASQUERADE
|
||||
iptables -A FORWARD -i pic0 -o wlan0 -j ACCEPT
|
||||
iptables -A FORWARD -i wlan0 -o pic0 -j ACCEPT
|
||||
./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.40.0.2:255.255.0.0:10.40.0.1: -a udpdnsclient:www.google.be:173.194.67.94
|
||||
*/
|
||||
void cb_udpdnsclient_getaddr(char *ip, void *arg)
|
||||
{
|
||||
uint8_t *id = (uint8_t *) arg;
|
||||
|
||||
if (!ip) {
|
||||
picoapp_dbg("%s: ERROR occured! (id: %u)\n", __FUNCTION__, *id);
|
||||
return;
|
||||
}
|
||||
|
||||
picoapp_dbg("%s: ip %s (id: %u)\n", __FUNCTION__, ip, *id);
|
||||
if (arg)
|
||||
PICO_FREE(arg);
|
||||
}
|
||||
|
||||
void cb_udpdnsclient_getname(char *name, void *arg)
|
||||
{
|
||||
uint8_t *id = (uint8_t *) arg;
|
||||
|
||||
if (!name) {
|
||||
picoapp_dbg("%s: ERROR occured! (id: %u)\n", __FUNCTION__, *id);
|
||||
return;
|
||||
}
|
||||
|
||||
picoapp_dbg("%s: name %s (id: %u)\n", __FUNCTION__, name, *id);
|
||||
if (arg)
|
||||
PICO_FREE(arg);
|
||||
}
|
||||
|
||||
void app_udpdnsclient(char *arg)
|
||||
{
|
||||
struct pico_ip4 nameserver;
|
||||
char *dname, *daddr;
|
||||
char *nxt;
|
||||
char *ipver;
|
||||
int v = 4;
|
||||
uint8_t *getaddr_id, *getname_id, *getaddr6_id, *getname6_id;
|
||||
|
||||
nxt = cpy_arg(&dname, arg);
|
||||
if (!dname || !nxt) {
|
||||
picoapp_dbg(" udpdnsclient expects the following format: udpdnsclient:dest_name:dest_ip:[ipv6]\n");
|
||||
exit(255);
|
||||
}
|
||||
|
||||
nxt = cpy_arg(&daddr, nxt);
|
||||
if (!daddr || !nxt) {
|
||||
picoapp_dbg(" udpdnsclient expects the following format: udpdnsclient:dest_name:dest_ip:[ipv6]\n");
|
||||
exit(255);
|
||||
}
|
||||
|
||||
nxt = cpy_arg(&ipver, nxt);
|
||||
if (!ipver || strcmp("ipv6", ipver) != 0)
|
||||
v = 4;
|
||||
else
|
||||
v = 6;
|
||||
|
||||
picoapp_dbg("UDP DNS client started.\n");
|
||||
|
||||
picoapp_dbg("----- Deleting non existant nameserver -----\n");
|
||||
pico_string_to_ipv4("127.0.0.1", &nameserver.addr);
|
||||
pico_dns_client_nameserver(&nameserver, PICO_DNS_NS_DEL);
|
||||
picoapp_dbg("----- Adding 8.8.8.8 nameserver -----\n");
|
||||
pico_string_to_ipv4("8.8.8.8", &nameserver.addr);
|
||||
pico_dns_client_nameserver(&nameserver, PICO_DNS_NS_ADD);
|
||||
picoapp_dbg("----- Deleting 8.8.8.8 nameserver -----\n");
|
||||
pico_string_to_ipv4("8.8.8.8", &nameserver.addr);
|
||||
pico_dns_client_nameserver(&nameserver, PICO_DNS_NS_DEL);
|
||||
picoapp_dbg("----- Adding 8.8.8.8 nameserver -----\n");
|
||||
pico_string_to_ipv4("8.8.8.8", &nameserver.addr);
|
||||
pico_dns_client_nameserver(&nameserver, PICO_DNS_NS_ADD);
|
||||
picoapp_dbg("----- Adding 8.8.4.4 nameserver -----\n");
|
||||
pico_string_to_ipv4("8.8.4.4", &nameserver.addr);
|
||||
pico_dns_client_nameserver(&nameserver, PICO_DNS_NS_ADD);
|
||||
if (!IPV6_MODE) {
|
||||
if (v == 4) {
|
||||
picoapp_dbg("Mode: IPv4\n");
|
||||
getaddr_id = calloc(1, sizeof(uint8_t));
|
||||
*getaddr_id = 1;
|
||||
picoapp_dbg(">>>>> DNS GET ADDR OF %s\n", dname);
|
||||
pico_dns_client_getaddr(dname, &cb_udpdnsclient_getaddr, getaddr_id);
|
||||
|
||||
getname_id = calloc(1, sizeof(uint8_t));
|
||||
*getname_id = 2;
|
||||
picoapp_dbg(">>>>> DNS GET NAME OF %s\n", daddr);
|
||||
pico_dns_client_getname(daddr, &cb_udpdnsclient_getname, getname_id);
|
||||
return;
|
||||
}
|
||||
|
||||
picoapp_dbg("Mode: IPv6\n");
|
||||
|
||||
#ifdef PICO_SUPPORT_IPV6
|
||||
getaddr6_id = calloc(1, sizeof(uint8_t));
|
||||
*getaddr6_id = 3;
|
||||
picoapp_dbg(">>>>> DNS GET ADDR6 OF %s\n", dname);
|
||||
pico_dns_client_getaddr6(dname, &cb_udpdnsclient_getaddr, getaddr6_id);
|
||||
getname6_id = calloc(1, sizeof(uint8_t));
|
||||
*getname6_id = 4;
|
||||
picoapp_dbg(">>>>> DNS GET NAME OF ipv6 addr 2a00:1450:400c:c06::64\n");
|
||||
pico_dns_client_getname6("2a00:1450:400c:c06::64", &cb_udpdnsclient_getname, getname6_id);
|
||||
#endif
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
/*** END UDP DNS CLIENT ***/
|
||||
142
kernel/picotcp/test/examples/iperfc.c
Normal file
142
kernel/picotcp/test/examples/iperfc.c
Normal file
@ -0,0 +1,142 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include "pico_ipv6.h"
|
||||
#include "pico_stack.h"
|
||||
#include "pico_socket.h"
|
||||
#include "utils.h"
|
||||
|
||||
#define DURATION 30
|
||||
|
||||
struct iperf_hdr {
|
||||
int32_t flags; /* 0 */
|
||||
int32_t numThreads; /* 1 */
|
||||
int32_t mPort; /* 5001 */
|
||||
int32_t bufferlen; /* 0 */
|
||||
int32_t mWinBand; /* 0 */
|
||||
int32_t mAmount; /* 0xfffffc18 */
|
||||
};
|
||||
|
||||
#define IPERF_PORT 5001
|
||||
#define MTU 1444
|
||||
#define SEND_BUF_SIZ (1024 * 2048)
|
||||
|
||||
char *cpy_arg(char **dst, char *str);
|
||||
extern int IPV6_MODE;
|
||||
|
||||
static pico_time deadline;
|
||||
|
||||
static void panic(void)
|
||||
{
|
||||
for(;; ) ;
|
||||
}
|
||||
|
||||
static char buf[MTU] = {};
|
||||
|
||||
static void buf_paint(void)
|
||||
{
|
||||
char paint[11] = "0123456789";
|
||||
int i;
|
||||
for (i = 0; i < MTU; i++) {
|
||||
buf[i] = paint[i % 10];
|
||||
}
|
||||
}
|
||||
|
||||
static void send_hdr(struct pico_socket *s)
|
||||
{
|
||||
struct iperf_hdr hdr = {};
|
||||
hdr.numThreads = long_be(1);
|
||||
hdr.mPort = long_be(5001);
|
||||
hdr.mAmount = long_be(0xfffffc18);
|
||||
pico_socket_write(s, &hdr, sizeof(hdr));
|
||||
deadline = PICO_TIME_MS() + DURATION * 1000;
|
||||
}
|
||||
|
||||
static void iperf_cb(uint16_t ev, struct pico_socket *s)
|
||||
{
|
||||
int r;
|
||||
static int end = 0;
|
||||
if (ev & PICO_SOCK_EV_CONN) {
|
||||
send_hdr(s);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((!end) && (ev & PICO_SOCK_EV_WR)) {
|
||||
if (PICO_TIME_MS() > deadline) {
|
||||
pico_socket_close(s);
|
||||
if (!pico_timer_add(2000, deferred_exit, NULL)) {
|
||||
printf("Failed to start exit timer, exiting now\n");
|
||||
exit(1);
|
||||
}
|
||||
end++;
|
||||
}
|
||||
|
||||
pico_socket_write(s, buf, MTU);
|
||||
}
|
||||
|
||||
if (!(end) && (ev & (PICO_SOCK_EV_FIN | PICO_SOCK_EV_CLOSE))) {
|
||||
if (!pico_timer_add(2000, deferred_exit, NULL)) {
|
||||
printf("Failed to start exit timer, exiting now\n");
|
||||
exit(1);
|
||||
}
|
||||
end++;
|
||||
}
|
||||
}
|
||||
|
||||
static void iperfc_socket_setup(union pico_address *addr, uint16_t family)
|
||||
{
|
||||
int yes = 1;
|
||||
uint16_t send_port = 0;
|
||||
struct pico_socket *s = NULL;
|
||||
uint32_t bufsize = SEND_BUF_SIZ;
|
||||
send_port = short_be(5001);
|
||||
s = pico_socket_open(family, PICO_PROTO_TCP, &iperf_cb);
|
||||
pico_socket_setoption(s, PICO_SOCKET_OPT_SNDBUF, &bufsize);
|
||||
pico_socket_connect(s, addr, send_port);
|
||||
}
|
||||
|
||||
void app_iperfc(char *arg)
|
||||
{
|
||||
struct pico_ip4 my_eth_addr, netmask;
|
||||
struct pico_device *pico_dev_eth;
|
||||
char *daddr = NULL, *dport = NULL;
|
||||
char *nxt = arg;
|
||||
uint16_t send_port = 0, listen_port = short_be(5001);
|
||||
int i = 0, ret = 0, yes = 1;
|
||||
struct pico_socket *s = NULL;
|
||||
uint16_t family = PICO_PROTO_IPV4;
|
||||
union pico_address dst = {
|
||||
.ip4 = {0}, .ip6 = {{0}}
|
||||
};
|
||||
union pico_address inaddr_any = {
|
||||
.ip4 = {0}, .ip6 = {{0}}
|
||||
};
|
||||
|
||||
/* start of argument parsing */
|
||||
if (nxt) {
|
||||
nxt = cpy_arg(&daddr, arg);
|
||||
if (daddr) {
|
||||
if (!IPV6_MODE)
|
||||
pico_string_to_ipv4(daddr, &dst.ip4.addr);
|
||||
|
||||
#ifdef PICO_SUPPORT_IPV6
|
||||
else {
|
||||
pico_string_to_ipv6(daddr, dst.ip6.addr);
|
||||
family = PICO_PROTO_IPV6;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
/* missing dest_addr */
|
||||
goto out;
|
||||
}
|
||||
|
||||
iperfc_socket_setup(&dst, family);
|
||||
return;
|
||||
out:
|
||||
dbg("Error parsing options!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
83
kernel/picotcp/test/examples/mdns.c
Normal file
83
kernel/picotcp/test/examples/mdns.c
Normal file
@ -0,0 +1,83 @@
|
||||
#include "utils.h"
|
||||
#include "pico_dns_common.h"
|
||||
#include "pico_mdns.h"
|
||||
#include "pico_ipv4.h"
|
||||
#include "pico_addressing.h"
|
||||
|
||||
/*** START MDNS ***/
|
||||
|
||||
#ifdef PICO_SUPPORT_MDNS
|
||||
|
||||
#define SECONDS 10
|
||||
|
||||
static int fully_initialized = 0;
|
||||
|
||||
void mdns_init_callback( pico_mdns_rtree *rtree,
|
||||
char *str,
|
||||
void *arg )
|
||||
{
|
||||
printf("\nInitialised with hostname: %s\n\n", str);
|
||||
|
||||
fully_initialized = 1;
|
||||
}
|
||||
|
||||
void app_mdns(char *arg, struct pico_ip4 address)
|
||||
{
|
||||
char *hostname, *peername;
|
||||
char *nxt = arg;
|
||||
uint64_t starttime = 0;
|
||||
int once = 0;
|
||||
|
||||
if (!nxt)
|
||||
exit(255);
|
||||
|
||||
nxt = cpy_arg(&hostname, nxt);
|
||||
if(!hostname) {
|
||||
exit(255);
|
||||
}
|
||||
|
||||
if(!nxt) {
|
||||
printf("Not enough args supplied!\n");
|
||||
exit(255);
|
||||
}
|
||||
|
||||
nxt = cpy_arg(&peername, nxt);
|
||||
if(!peername) {
|
||||
exit(255);
|
||||
}
|
||||
|
||||
printf("\nStarting mDNS module...\n");
|
||||
if (pico_mdns_init(hostname, address, &mdns_init_callback, NULL)) {
|
||||
printf("Initialisation returned with Error!\n");
|
||||
exit(255);
|
||||
}
|
||||
|
||||
printf("\nTry reinitialising mDNS\n");
|
||||
if (pico_mdns_init(hostname, address, &mdns_init_callback, NULL)) {
|
||||
printf("Initialisation returned with Error!\n");
|
||||
exit(255);
|
||||
}
|
||||
|
||||
printf("DONE - Re-initialising mDNS module.\n");
|
||||
|
||||
starttime = PICO_TIME_MS();
|
||||
printf("Starting time: %d\n", starttime);
|
||||
|
||||
while(1) {
|
||||
pico_stack_tick();
|
||||
usleep(2000);
|
||||
|
||||
if (((PICO_TIME_MS() - starttime) > SECONDS * 1000) && fully_initialized && !once) {
|
||||
printf("\nTry reinitialising mDNS (a second time)\n");
|
||||
if (pico_mdns_init(hostname, address, &mdns_init_callback, NULL)) {
|
||||
printf("Initialisation returned with Error!\n");
|
||||
exit(255);
|
||||
}
|
||||
once = 1;
|
||||
printf("DONE - Re-initialising mDNS module. (a second time)\n");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/*** END MDNS ***/
|
||||
182
kernel/picotcp/test/examples/multicast_ip6_recv.c
Normal file
182
kernel/picotcp/test/examples/multicast_ip6_recv.c
Normal file
@ -0,0 +1,182 @@
|
||||
#include "utils.h"
|
||||
#include <pico_ipv6.h>
|
||||
#include <pico_socket.h>
|
||||
|
||||
extern void app_udpecho(char *arg);
|
||||
|
||||
/*** START Multicast RECEIVE + ECHO ***/
|
||||
/*
|
||||
* multicast receive expects the following format: mcastreceive:link_addr:mcast_addr:listen_port:sendto_port
|
||||
* link_addr: mcastreceive picoapp IP address
|
||||
* mcast_addr: multicast IP address to receive
|
||||
* listen_port: port number on which the mcastreceive listens
|
||||
* sendto_port: port number to echo multicast traffic to (echo to originating IP address)
|
||||
*
|
||||
* f.e.: ./build/test/picoapp.elf --vde pic1:/tmp/pic0.ctl:10.40.0.3:255.255.0.0: -a mcastreceive:10.40.0.3:224.7.7.7:6667:6667
|
||||
*/
|
||||
extern struct udpclient_pas *udpclient_pas;
|
||||
extern struct udpecho_pas *udpecho_pas;
|
||||
#ifdef PICO_SUPPORT_MCAST
|
||||
void app_mcastreceive_ipv6(char *arg)
|
||||
{
|
||||
char *new_arg = NULL, *p = NULL, *nxt = arg;
|
||||
char *laddr = NULL, *maddr = NULL, *lport = NULL, *sport = NULL;
|
||||
uint16_t listen_port = 0;
|
||||
union pico_address inaddr_link = {
|
||||
0
|
||||
}, inaddr_mcast = {
|
||||
0
|
||||
}, src[5] = {
|
||||
{.ip6 = { 0xfe, 0x80, 0x00, 0x00, 0x00, 0, 0, 0, 0, 0, 0, 0, 0xac, 0x10, 0x01, 0 }},
|
||||
{.ip6 = { 0xfe, 0x80, 0x00, 0x00, 0x00, 0, 0, 0, 0, 0, 0, 0, 0xac, 0x10, 0x01, 0x10}},
|
||||
{.ip6 = { 0xfe, 0x80, 0x00, 0x00, 0x00, 0, 0, 0, 0, 0, 0, 0, 0xac, 0x10, 0x01, 0x01 }},
|
||||
{.ip6 = { 0xff, 0x00, 0x00, 0x00, 0x00, 0, 0, 0, 0, 0, 0, 0, 0xe0, 0x01, 0x01, 0x01 }},
|
||||
};
|
||||
struct pico_ip_mreq mreq = ZERO_MREQ_IP6;
|
||||
struct pico_ip_mreq_source mreq_source = ZERO_MREQ_SRC_IP6;
|
||||
/* start of parameter parsing */
|
||||
if (nxt) {
|
||||
nxt = cpy_arg(&laddr, nxt);
|
||||
if (laddr) {
|
||||
pico_string_to_ipv6(laddr, &inaddr_link.ip6.addr[0]);
|
||||
} else {
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
/* no arguments */
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (nxt) {
|
||||
nxt = cpy_arg(&maddr, nxt);
|
||||
if (maddr) {
|
||||
pico_string_to_ipv6(maddr, &inaddr_mcast.ip6.addr[0]);
|
||||
} else {
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
/* missing multicast address */
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (nxt) {
|
||||
nxt = cpy_arg(&lport, nxt);
|
||||
if (lport && atoi(lport)) {
|
||||
listen_port = short_be(atoi(lport));
|
||||
} else {
|
||||
/* incorrect listen_port */
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
/* missing listen_port */
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (nxt) {
|
||||
nxt = cpy_arg(&sport, nxt);
|
||||
if (sport && atoi(sport)) {
|
||||
/* unused at this moment */
|
||||
/* send_port = short_be(atoi(sport)); */
|
||||
} else {
|
||||
/* incorrect send_port */
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
/* missing send_port */
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* end of parameter parsing */
|
||||
|
||||
printf("\n%s: multicast receive started. Receiving packets on [%s]:%d\n\n", __FUNCTION__, maddr, short_be(listen_port));
|
||||
|
||||
/* udpecho:bind_addr:listen_port[:sendto_port:datasize] */
|
||||
new_arg = calloc(1, strlen(laddr) + 1 + strlen(lport) + 1 + strlen(sport) + strlen(",64:") + 1);
|
||||
p = strcat(new_arg, laddr);
|
||||
p = strcat(p + strlen(laddr), ",");
|
||||
p = strcat(p + 1, lport);
|
||||
p = strcat(p + strlen(lport), ",");
|
||||
p = strcat(p + 1, sport);
|
||||
p = strcat(p + strlen(sport), ",64,");
|
||||
|
||||
/* DAD needs to verify the link address before we can continue */
|
||||
while(!pico_ipv6_link_get(&inaddr_link.ip6)) {
|
||||
pico_stack_tick();
|
||||
usleep(2000);
|
||||
}
|
||||
app_udpecho(new_arg);
|
||||
|
||||
memcpy(&mreq.mcast_group_addr, &inaddr_mcast, sizeof(struct pico_ip6));
|
||||
memcpy( &mreq_source.mcast_group_addr, &inaddr_mcast, sizeof(struct pico_ip6));
|
||||
memcpy(&mreq.mcast_link_addr, &inaddr_link, sizeof(struct pico_ip6));
|
||||
memcpy(&mreq_source.mcast_link_addr, &inaddr_link, sizeof(struct pico_ip6));
|
||||
memcpy(&mreq_source.mcast_source_addr, &src[0], sizeof(struct pico_ip6));
|
||||
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_ADD_MEMBERSHIP, &mreq) < 0) {
|
||||
printf("%s: socket_setoption PICO_IP_ADD_MEMBERSHIP failed: %s\n", __FUNCTION__, strerror(pico_err));
|
||||
}
|
||||
|
||||
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_DROP_MEMBERSHIP, &mreq) < 0) {
|
||||
printf("%s: socket_setoption PICO_IP_DROP_MEMBERSHIP failed: %s\n", __FUNCTION__, strerror(pico_err));
|
||||
}
|
||||
|
||||
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_ADD_MEMBERSHIP, &mreq) < 0) {
|
||||
printf("%s: socket_setoption PICO_IP_ADD_MEMBERSHIP failed: %s\n", __FUNCTION__, strerror(pico_err));
|
||||
}
|
||||
|
||||
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_BLOCK_SOURCE, &mreq_source) < 0) {
|
||||
printf("%s: socket_setoption PICO_IP_BLOCK_SOURCE failed: %s\n", __FUNCTION__, strerror(pico_err));
|
||||
}
|
||||
|
||||
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_UNBLOCK_SOURCE, &mreq_source) < 0) {
|
||||
printf("%s: socket_setoption PICO_IP_UNBLOCK_SOURCE failed: %s\n", __FUNCTION__, strerror(pico_err));
|
||||
}
|
||||
|
||||
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_DROP_MEMBERSHIP, &mreq) < 0) {
|
||||
printf("%s: socket_setoption PICO_IP_DROP_MEMBERSHIP failed: %s\n", __FUNCTION__, strerror(pico_err));
|
||||
}
|
||||
|
||||
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source) < 0) {
|
||||
printf("%s: socket_setoption PICO_IP_ADD_SOURCE_MEMBERSHIP: %s\n", __FUNCTION__, strerror(pico_err));
|
||||
}
|
||||
|
||||
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source) < 0) {
|
||||
printf("%s: socket_setoption PICO_IP_DROP_SOURCE_MEMBERSHIP: %s\n", __FUNCTION__, strerror(pico_err));
|
||||
}
|
||||
|
||||
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source) < 0) {
|
||||
printf("%s: socket_setoption PICO_IP_ADD_SOURCE_MEMBERSHIP: %s\n", __FUNCTION__, strerror(pico_err));
|
||||
}
|
||||
|
||||
memcpy(&mreq_source.mcast_source_addr, &src[1], sizeof(struct pico_ip6));
|
||||
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source) < 0) {
|
||||
printf("%s: socket_setoption PICO_IP_ADD_SOURCE_MEMBERSHIP: %s\n", __FUNCTION__, strerror(pico_err));
|
||||
}
|
||||
|
||||
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_DROP_MEMBERSHIP, &mreq) < 0) {
|
||||
printf("%s: socket_setoption PICO_IP_DROP_MEMBERSHIP failed: %s\n", __FUNCTION__, strerror(pico_err));
|
||||
}
|
||||
|
||||
memcpy(&mreq_source.mcast_source_addr, &src[2], sizeof(struct pico_ip6));
|
||||
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source) < 0) {
|
||||
printf("%s: socket_setoption PICO_IP_ADD_SOURCE_MEMBERSHIP: %s\n", __FUNCTION__, strerror(pico_err));
|
||||
}
|
||||
|
||||
memcpy(&mreq_source.mcast_group_addr, &src[3], sizeof(struct pico_ip6));
|
||||
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source) < 0) {
|
||||
printf("%s: socket_setoption PICO_IP_ADD_SOURCE_MEMBERSHIP: %s\n", __FUNCTION__, strerror(pico_err));
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
out:
|
||||
fprintf(stderr, "mcastreceive expects the following format: mcastreceive:link_addr:mcast_addr:listen_port[:send_port]\n");
|
||||
exit(255);
|
||||
}
|
||||
#else
|
||||
void app_mcastreceive_ipv6(char *arg)
|
||||
{
|
||||
printf("ERROR: PICO_SUPPORT_MCAST disabled\n");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
/*** END Multicast RECEIVE + ECHO ***/
|
||||
140
kernel/picotcp/test/examples/multicast_ip6_send.c
Normal file
140
kernel/picotcp/test/examples/multicast_ip6_send.c
Normal file
@ -0,0 +1,140 @@
|
||||
#include "utils.h"
|
||||
#include <pico_ipv4.h>
|
||||
#include <pico_ipv6.h>
|
||||
#include <pico_socket.h>
|
||||
|
||||
extern void app_udpclient(char *arg);
|
||||
/*** START Multicast SEND ***/
|
||||
/*
|
||||
* multicast send expects the following format: mcastsend:link_addr:mcast_addr:sendto_port:listen_port
|
||||
* link_addr: mcastsend picoapp IP address
|
||||
* mcast_addr: multicast IP address to send to
|
||||
* sendto_port: port number to send multicast traffic to
|
||||
* listen_port: port number on which the mcastsend can receive data
|
||||
*
|
||||
* f.e.: ./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.40.0.2:255.255.255.0: -a mcastsend:10.40.0.2:224.7.7.7:6667:6667
|
||||
*/
|
||||
extern struct udpclient_pas *udpclient_pas;
|
||||
#ifdef PICO_SUPPORT_MCAST
|
||||
void app_mcastsend_ipv6(char *arg)
|
||||
{
|
||||
int retval = 0;
|
||||
char *maddr = NULL, *laddr = NULL, *lport = NULL, *sport = NULL;
|
||||
uint16_t sendto_port = 0;
|
||||
struct pico_ip6 inaddr_link = {
|
||||
0
|
||||
}, inaddr_mcast = {
|
||||
0
|
||||
};
|
||||
char *new_arg = NULL, *p = NULL, *nxt = arg;
|
||||
struct pico_ip_mreq mreq = ZERO_MREQ_IP6;
|
||||
|
||||
/* start of parameter parsing */
|
||||
if (nxt) {
|
||||
nxt = cpy_arg(&laddr, nxt);
|
||||
if (laddr) {
|
||||
pico_string_to_ipv6(laddr, &inaddr_link.addr[0]);
|
||||
} else {
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
/* no arguments */
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (nxt) {
|
||||
nxt = cpy_arg(&maddr, nxt);
|
||||
if (maddr) {
|
||||
pico_string_to_ipv6(maddr, &inaddr_mcast.addr[0]);
|
||||
} else {
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
/* missing multicast address */
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (nxt) {
|
||||
nxt = cpy_arg(&sport, nxt);
|
||||
if (sport && atoi(sport)) {
|
||||
sendto_port = short_be(atoi(sport));
|
||||
} else {
|
||||
/* incorrect send_port */
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
/* missing send_port */
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (nxt) {
|
||||
nxt = cpy_arg(&lport, nxt);
|
||||
if (lport && atoi(lport)) {
|
||||
/* unused at this moment */
|
||||
/* listen_port = short_be(atoi(lport)); */
|
||||
} else {
|
||||
/* incorrect listen_port */
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
/* missing listen_port */
|
||||
goto out;
|
||||
}
|
||||
|
||||
picoapp_dbg("\n%s: mcastsend started. Sending packets to %s:%u\n\n", __FUNCTION__, maddr, short_be(sendto_port));
|
||||
|
||||
/* udpclient:dest_addr:sendto_port[:listen_port:datasize:loops:subloops] */
|
||||
new_arg = calloc(1, strlen(maddr) + 1 + strlen(sport) + 1 + strlen(lport) + strlen(",64,10,5,") + 1);
|
||||
p = strcat(new_arg, maddr);
|
||||
p = strcat(p + strlen(maddr), ",");
|
||||
p = strcat(p + 1, sport);
|
||||
p = strcat(p + strlen(sport), ",");
|
||||
p = strcat(p + 1, lport);
|
||||
p = strcat(p + strlen(lport), ",64,10,5,");
|
||||
|
||||
/* DAD needs to verify the link address before we can continue */
|
||||
while(!pico_ipv6_link_get(&inaddr_link)) {
|
||||
pico_stack_tick();
|
||||
usleep(2000);
|
||||
}
|
||||
app_udpclient(new_arg);
|
||||
|
||||
memcpy(&mreq.mcast_group_addr, &inaddr_mcast, sizeof(struct pico_ip6));
|
||||
memcpy(&mreq.mcast_link_addr, &inaddr_link, sizeof(struct pico_ip6));
|
||||
if(pico_socket_setoption(udpclient_pas->s, PICO_IP_ADD_MEMBERSHIP, &mreq) < 0) {
|
||||
picoapp_dbg("%s: socket_setoption PICO_IP_ADD_MEMBERSHIP failed: %s\n", __FUNCTION__, strerror(pico_err));
|
||||
retval = 1;
|
||||
}
|
||||
|
||||
if (new_arg)
|
||||
free(new_arg);
|
||||
|
||||
if (lport)
|
||||
free(lport);
|
||||
|
||||
if (maddr)
|
||||
free(maddr);
|
||||
|
||||
if (sport)
|
||||
free(sport);
|
||||
|
||||
if (laddr)
|
||||
free(laddr);
|
||||
|
||||
if (retval)
|
||||
exit(retval);
|
||||
|
||||
return;
|
||||
|
||||
out:
|
||||
picoapp_dbg("mcastsend expects the following format: mcastsend:link_addr:mcast_addr:sendto_port:listen_port\n");
|
||||
exit(255);
|
||||
}
|
||||
#else
|
||||
void app_mcastsend_ipv6(char *arg)
|
||||
{
|
||||
picoapp_dbg("ERROR: PICO_SUPPORT_MCAST disabled\n");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
/*** END Multicast SEND ***/
|
||||
171
kernel/picotcp/test/examples/multicast_recv.c
Normal file
171
kernel/picotcp/test/examples/multicast_recv.c
Normal file
@ -0,0 +1,171 @@
|
||||
#include "utils.h"
|
||||
#include <pico_ipv4.h>
|
||||
#include <pico_socket.h>
|
||||
|
||||
extern void app_udpecho(char *arg);
|
||||
|
||||
/*** START Multicast RECEIVE + ECHO ***/
|
||||
/*
|
||||
* multicast receive expects the following format: mcastreceive:link_addr:mcast_addr:listen_port:sendto_port
|
||||
* link_addr: mcastreceive picoapp IP address
|
||||
* mcast_addr: multicast IP address to receive
|
||||
* listen_port: port number on which the mcastreceive listens
|
||||
* sendto_port: port number to echo multicast traffic to (echo to originating IP address)
|
||||
*
|
||||
* f.e.: ./build/test/picoapp.elf --vde pic1:/tmp/pic0.ctl:10.40.0.3:255.255.0.0: -a mcastreceive:10.40.0.3:224.7.7.7:6667:6667
|
||||
*/
|
||||
extern struct udpclient_pas *udpclient_pas;
|
||||
extern struct udpecho_pas *udpecho_pas;
|
||||
#ifdef PICO_SUPPORT_MCAST
|
||||
void app_mcastreceive(char *arg)
|
||||
{
|
||||
char *new_arg = NULL, *p = NULL, *nxt = arg;
|
||||
char *laddr = NULL, *maddr = NULL, *lport = NULL, *sport = NULL;
|
||||
uint16_t listen_port = 0;
|
||||
union pico_address inaddr_link = {
|
||||
0
|
||||
}, inaddr_mcast = {
|
||||
0
|
||||
};
|
||||
struct pico_ip_mreq mreq = ZERO_MREQ;
|
||||
struct pico_ip_mreq_source mreq_source = ZERO_MREQ_SRC;
|
||||
|
||||
/* start of parameter parsing */
|
||||
if (nxt) {
|
||||
nxt = cpy_arg(&laddr, nxt);
|
||||
if (laddr) {
|
||||
pico_string_to_ipv4(laddr, &inaddr_link.ip4.addr);
|
||||
} else {
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
/* no arguments */
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (nxt) {
|
||||
nxt = cpy_arg(&maddr, nxt);
|
||||
if (maddr) {
|
||||
pico_string_to_ipv4(maddr, &inaddr_mcast.ip4.addr);
|
||||
} else {
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
/* missing multicast address */
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (nxt) {
|
||||
nxt = cpy_arg(&lport, nxt);
|
||||
if (lport && atoi(lport)) {
|
||||
listen_port = short_be(atoi(lport));
|
||||
} else {
|
||||
/* incorrect listen_port */
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
/* missing listen_port */
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (nxt) {
|
||||
nxt = cpy_arg(&sport, nxt);
|
||||
if (sport && atoi(sport)) {
|
||||
/* unused at this moment */
|
||||
/* send_port = short_be(atoi(sport)); */
|
||||
} else {
|
||||
/* incorrect send_port */
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
/* missing send_port */
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* end of parameter parsing */
|
||||
|
||||
printf("\n%s: multicast receive started. Receiving packets on %s:%d\n\n", __FUNCTION__, maddr, short_be(listen_port));
|
||||
|
||||
/* udpecho:bind_addr:listen_port[:sendto_port:datasize] */
|
||||
new_arg = calloc(1, strlen(laddr) + 1 + strlen(lport) + 1 + strlen(sport) + strlen(":64:") + 1);
|
||||
p = strcat(new_arg, laddr);
|
||||
p = strcat(p + strlen(laddr), ":");
|
||||
p = strcat(p + 1, lport);
|
||||
p = strcat(p + strlen(lport), ":");
|
||||
p = strcat(p + 1, sport);
|
||||
p = strcat(p + strlen(sport), ":64:");
|
||||
|
||||
app_udpecho(new_arg);
|
||||
|
||||
mreq.mcast_group_addr = mreq_source.mcast_group_addr = inaddr_mcast;
|
||||
mreq.mcast_link_addr = mreq_source.mcast_link_addr = inaddr_link;
|
||||
mreq_source.mcast_source_addr.ip4.addr = long_be(0XAC100101);
|
||||
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_ADD_MEMBERSHIP, &mreq) < 0) {
|
||||
printf("%s: socket_setoption PICO_IP_ADD_MEMBERSHIP failed: %s\n", __FUNCTION__, strerror(pico_err));
|
||||
}
|
||||
|
||||
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_DROP_MEMBERSHIP, &mreq) < 0) {
|
||||
printf("%s: socket_setoption PICO_IP_DROP_MEMBERSHIP failed: %s\n", __FUNCTION__, strerror(pico_err));
|
||||
}
|
||||
|
||||
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_ADD_MEMBERSHIP, &mreq) < 0) {
|
||||
printf("%s: socket_setoption PICO_IP_ADD_MEMBERSHIP failed: %s\n", __FUNCTION__, strerror(pico_err));
|
||||
}
|
||||
|
||||
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_BLOCK_SOURCE, &mreq_source) < 0) {
|
||||
printf("%s: socket_setoption PICO_IP_BLOCK_SOURCE failed: %s\n", __FUNCTION__, strerror(pico_err));
|
||||
}
|
||||
|
||||
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_UNBLOCK_SOURCE, &mreq_source) < 0) {
|
||||
printf("%s: socket_setoption PICO_IP_UNBLOCK_SOURCE failed: %s\n", __FUNCTION__, strerror(pico_err));
|
||||
}
|
||||
|
||||
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_DROP_MEMBERSHIP, &mreq) < 0) {
|
||||
printf("%s: socket_setoption PICO_IP_DROP_MEMBERSHIP failed: %s\n", __FUNCTION__, strerror(pico_err));
|
||||
}
|
||||
|
||||
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source) < 0) {
|
||||
printf("%s: socket_setoption PICO_IP_ADD_SOURCE_MEMBERSHIP: %s\n", __FUNCTION__, strerror(pico_err));
|
||||
}
|
||||
|
||||
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_DROP_SOURCE_MEMBERSHIP, &mreq_source) < 0) {
|
||||
printf("%s: socket_setoption PICO_IP_DROP_SOURCE_MEMBERSHIP: %s\n", __FUNCTION__, strerror(pico_err));
|
||||
}
|
||||
|
||||
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source) < 0) {
|
||||
printf("%s: socket_setoption PICO_IP_ADD_SOURCE_MEMBERSHIP: %s\n", __FUNCTION__, strerror(pico_err));
|
||||
}
|
||||
|
||||
mreq_source.mcast_source_addr.ip4.addr = long_be(0XAC10010A);
|
||||
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source) < 0) {
|
||||
printf("%s: socket_setoption PICO_IP_ADD_SOURCE_MEMBERSHIP: %s\n", __FUNCTION__, strerror(pico_err));
|
||||
}
|
||||
|
||||
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_DROP_MEMBERSHIP, &mreq) < 0) {
|
||||
printf("%s: socket_setoption PICO_IP_DROP_MEMBERSHIP failed: %s\n", __FUNCTION__, strerror(pico_err));
|
||||
}
|
||||
|
||||
mreq_source.mcast_source_addr.ip4.addr = long_be(0XAC100101);
|
||||
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source) < 0) {
|
||||
printf("%s: socket_setoption PICO_IP_ADD_SOURCE_MEMBERSHIP: %s\n", __FUNCTION__, strerror(pico_err));
|
||||
}
|
||||
|
||||
mreq_source.mcast_group_addr.ip4.addr = long_be(0XE0010101);
|
||||
if(pico_socket_setoption(udpecho_pas->s, PICO_IP_ADD_SOURCE_MEMBERSHIP, &mreq_source) < 0) {
|
||||
printf("%s: socket_setoption PICO_IP_ADD_SOURCE_MEMBERSHIP: %s\n", __FUNCTION__, strerror(pico_err));
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
out:
|
||||
fprintf(stderr, "mcastreceive expects the following format: mcastreceive:link_addr:mcast_addr:listen_port[:send_port]\n");
|
||||
exit(255);
|
||||
}
|
||||
#else
|
||||
void app_mcastreceive(char *arg)
|
||||
{
|
||||
printf("ERROR: PICO_SUPPORT_MCAST disabled\n");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
/*** END Multicast RECEIVE + ECHO ***/
|
||||
129
kernel/picotcp/test/examples/multicast_send.c
Normal file
129
kernel/picotcp/test/examples/multicast_send.c
Normal file
@ -0,0 +1,129 @@
|
||||
#include "utils.h"
|
||||
#include <pico_ipv4.h>
|
||||
#include <pico_socket.h>
|
||||
|
||||
extern void app_udpclient(char *arg);
|
||||
/*** START Multicast SEND ***/
|
||||
/*
|
||||
* multicast send expects the following format: mcastsend:link_addr:mcast_addr:sendto_port:listen_port
|
||||
* link_addr: mcastsend picoapp IP address
|
||||
* mcast_addr: multicast IP address to send to
|
||||
* sendto_port: port number to send multicast traffic to
|
||||
* listen_port: port number on which the mcastsend can receive data
|
||||
*
|
||||
* f.e.: ./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.40.0.2:255.255.255.0: -a mcastsend:10.40.0.2:224.7.7.7:6667:6667
|
||||
*/
|
||||
extern struct udpclient_pas *udpclient_pas;
|
||||
#ifdef PICO_SUPPORT_MCAST
|
||||
void app_mcastsend(char *arg)
|
||||
{
|
||||
char *maddr = NULL, *laddr = NULL, *lport = NULL, *sport = NULL;
|
||||
uint16_t sendto_port = 0;
|
||||
union pico_address inaddr_link = {
|
||||
0
|
||||
}, inaddr_mcast = {
|
||||
0
|
||||
};
|
||||
char *new_arg = NULL, *p = NULL, *nxt = arg;
|
||||
struct pico_ip_mreq mreq = ZERO_MREQ;
|
||||
|
||||
/* start of parameter parsing */
|
||||
if (nxt) {
|
||||
nxt = cpy_arg(&laddr, nxt);
|
||||
if (laddr) {
|
||||
pico_string_to_ipv4(laddr, &inaddr_link.ip4.addr);
|
||||
} else {
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
/* no arguments */
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (nxt) {
|
||||
nxt = cpy_arg(&maddr, nxt);
|
||||
if (maddr) {
|
||||
pico_string_to_ipv4(maddr, &inaddr_mcast.ip4.addr);
|
||||
} else {
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
/* missing multicast address */
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (nxt) {
|
||||
nxt = cpy_arg(&sport, nxt);
|
||||
if (sport && atoi(sport)) {
|
||||
sendto_port = short_be(atoi(sport));
|
||||
} else {
|
||||
/* incorrect send_port */
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
/* missing send_port */
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (nxt) {
|
||||
nxt = cpy_arg(&lport, nxt);
|
||||
if (lport && atoi(lport)) {
|
||||
/* unused at this moment */
|
||||
/* listen_port = short_be(atoi(lport)); */
|
||||
} else {
|
||||
/* incorrect listen_port */
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
/* missing listen_port */
|
||||
goto out;
|
||||
}
|
||||
|
||||
picoapp_dbg("\n%s: mcastsend started. Sending packets to %08X:%u\n\n", __FUNCTION__, long_be(inaddr_mcast.addr), short_be(sendto_port));
|
||||
|
||||
/* udpclient:dest_addr:sendto_port[:listen_port:datasize:loops:subloops] */
|
||||
new_arg = calloc(1, strlen(maddr) + 1 + strlen(sport) + 1 + strlen(lport) + strlen(":64:10:5:") + 1);
|
||||
p = strcat(new_arg, maddr);
|
||||
p = strcat(p + strlen(maddr), ":");
|
||||
p = strcat(p + 1, sport);
|
||||
p = strcat(p + strlen(sport), ":");
|
||||
p = strcat(p + 1, lport);
|
||||
p = strcat(p + strlen(lport), ":64:10:5:");
|
||||
|
||||
app_udpclient(new_arg);
|
||||
free(new_arg);
|
||||
|
||||
mreq.mcast_group_addr = inaddr_mcast;
|
||||
mreq.mcast_link_addr = inaddr_link;
|
||||
if(pico_socket_setoption(udpclient_pas->s, PICO_IP_ADD_MEMBERSHIP, &mreq) < 0) {
|
||||
picoapp_dbg("%s: socket_setoption PICO_IP_ADD_MEMBERSHIP failed: %s\n", __FUNCTION__, strerror(pico_err));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* free strdups */
|
||||
if (maddr)
|
||||
free(maddr);
|
||||
|
||||
if (laddr)
|
||||
free(laddr);
|
||||
|
||||
if (lport)
|
||||
free(lport);
|
||||
|
||||
if (sport)
|
||||
free(sport);
|
||||
|
||||
return;
|
||||
|
||||
out:
|
||||
picoapp_dbg("mcastsend expects the following format: mcastsend:link_addr:mcast_addr:sendto_port:listen_port\n");
|
||||
exit(255);
|
||||
}
|
||||
#else
|
||||
void app_mcastsend(char *arg)
|
||||
{
|
||||
picoapp_dbg("ERROR: PICO_SUPPORT_MCAST disabled\n");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
/*** END Multicast SEND ***/
|
||||
31
kernel/picotcp/test/examples/natbox.c
Normal file
31
kernel/picotcp/test/examples/natbox.c
Normal file
@ -0,0 +1,31 @@
|
||||
#include "utils.h"
|
||||
#include <pico_ipv4.h>
|
||||
#include <pico_nat.h>
|
||||
|
||||
/*** START NATBOX ***/
|
||||
void app_natbox(char *arg)
|
||||
{
|
||||
char *dest = NULL;
|
||||
struct pico_ip4 ipdst, pub_addr, priv_addr;
|
||||
struct pico_ipv4_link *link;
|
||||
|
||||
cpy_arg(&dest, arg);
|
||||
if (!dest) {
|
||||
fprintf(stderr, "natbox needs the following format: natbox:dst_addr\n");
|
||||
exit(255);
|
||||
}
|
||||
|
||||
pico_string_to_ipv4(dest, &ipdst.addr);
|
||||
link = pico_ipv4_link_get(&ipdst);
|
||||
if (!link) {
|
||||
fprintf(stderr, "natbox: Destination not found.\n");
|
||||
exit(255);
|
||||
}
|
||||
|
||||
pico_ipv4_nat_enable(link);
|
||||
pico_string_to_ipv4("10.50.0.10", &pub_addr.addr);
|
||||
pico_string_to_ipv4("10.40.0.08", &priv_addr.addr);
|
||||
pico_ipv4_port_forward(pub_addr, short_be(5555), priv_addr, short_be(6667), PICO_PROTO_UDP, PICO_NAT_PORT_FORWARD_ADD);
|
||||
fprintf(stderr, "natbox: started.\n");
|
||||
}
|
||||
/*** END NATBOX ***/
|
||||
11
kernel/picotcp/test/examples/noop.c
Normal file
11
kernel/picotcp/test/examples/noop.c
Normal file
@ -0,0 +1,11 @@
|
||||
/* NOOP */
|
||||
#include <pico_stack.h>
|
||||
void app_noop(void)
|
||||
{
|
||||
while(1) {
|
||||
pico_stack_tick();
|
||||
usleep(2000);
|
||||
}
|
||||
}
|
||||
|
||||
/* END NOOP */
|
||||
138
kernel/picotcp/test/examples/ping.c
Normal file
138
kernel/picotcp/test/examples/ping.c
Normal file
@ -0,0 +1,138 @@
|
||||
#include "utils.h"
|
||||
#include <pico_ipv4.h>
|
||||
#include <pico_ipv6.h>
|
||||
#include <pico_icmp4.h>
|
||||
#include <pico_icmp6.h>
|
||||
/*** START PING ***/
|
||||
#ifdef PICO_SUPPORT_PING
|
||||
#define NUM_PING 10
|
||||
|
||||
void cb_ping(struct pico_icmp4_stats *s)
|
||||
{
|
||||
char host[30];
|
||||
pico_ipv4_to_string(host, s->dst.addr);
|
||||
if (s->err == 0) {
|
||||
dbg("%lu bytes from %s: icmp_req=%lu ttl=%lu time=%lu ms\n", s->size, host, s->seq,
|
||||
s->ttl, (long unsigned int)s->time);
|
||||
if (s->seq >= NUM_PING)
|
||||
exit(0);
|
||||
} else {
|
||||
dbg("PING %lu to %s: Error %d\n", s->seq, host, s->err);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef PICO_SUPPORT_IPV6
|
||||
void cb_ping6(struct pico_icmp6_stats *s)
|
||||
{
|
||||
char host[50];
|
||||
pico_ipv6_to_string(host, s->dst.addr);
|
||||
if (s->err == 0) {
|
||||
dbg("%lu bytes from %s: icmp_req=%lu ttl=%lu time=%lu ms\n", s->size, host, s->seq,
|
||||
s->ttl, (long unsigned int)s->time);
|
||||
if (s->seq >= NUM_PING)
|
||||
exit(0);
|
||||
} else {
|
||||
dbg("PING %lu to %s: Error %d\n", s->seq, host, s->err);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void ping_abort_timer(pico_time now, void *_id)
|
||||
{
|
||||
int *id = (int *) _id;
|
||||
printf("Ping: aborting...\n");
|
||||
if (!IPV6_MODE)
|
||||
pico_icmp4_ping_abort(*id);
|
||||
|
||||
#ifdef PICO_SUPPORT_IPV6
|
||||
else
|
||||
pico_icmp6_ping_abort(*id);
|
||||
#endif
|
||||
}
|
||||
|
||||
void app_ping(char *arg)
|
||||
{
|
||||
char *dest = NULL;
|
||||
char *next = NULL;
|
||||
char *abort = NULL;
|
||||
char *delay = NULL;
|
||||
char *asize = NULL;
|
||||
int initial_delay = 0;
|
||||
struct pico_ip6 dst;
|
||||
static int id;
|
||||
int timeout = 0;
|
||||
int size = 64;
|
||||
|
||||
next = cpy_arg(&dest, arg);
|
||||
if (!dest) {
|
||||
fprintf(stderr, "ping needs the following format: ping:dst_addr:[size:[abort after N sec:[wait N sec before start]]]\n");
|
||||
exit(255);
|
||||
}
|
||||
pico_string_to_ipv6(dest, dst.addr);
|
||||
if (next) {
|
||||
next = cpy_arg(&asize, next);
|
||||
size = atoi(asize);
|
||||
free(asize);
|
||||
if (size <= 0) {
|
||||
size = 64; /* Default */
|
||||
}
|
||||
}
|
||||
|
||||
if (next) {
|
||||
next = cpy_arg(&abort, next);
|
||||
if (strlen(abort) > 0) {
|
||||
printf("Got arg: '%s'\n", abort);
|
||||
timeout = atoi(abort);
|
||||
if (timeout < 0) {
|
||||
fprintf(stderr, "ping needs the following format: ping:dst_addr:[size:[abort after N sec:[wait N sec before start]]]\n");
|
||||
exit(255);
|
||||
}
|
||||
printf("Aborting ping after %d seconds\n", timeout);
|
||||
}
|
||||
}
|
||||
|
||||
if (next) {
|
||||
next = cpy_arg(&delay, next);
|
||||
if (strlen(delay) > 0) {
|
||||
initial_delay = atoi(delay);
|
||||
if (initial_delay > 0) {
|
||||
printf("Initial delay: %d seconds\n", initial_delay);
|
||||
initial_delay = PICO_TIME_MS() + initial_delay * 1000;
|
||||
while (PICO_TIME_MS() < initial_delay) {
|
||||
pico_stack_tick();
|
||||
usleep(10000);
|
||||
}
|
||||
}
|
||||
}
|
||||
free(delay);
|
||||
}
|
||||
printf("Starting ping.\n");
|
||||
|
||||
if (!IPV6_MODE)
|
||||
id = pico_icmp4_ping(dest, NUM_PING, 1000, 10000, size, cb_ping);
|
||||
|
||||
#ifdef PICO_SUPPORT_IPV6
|
||||
else
|
||||
id = pico_icmp6_ping(dest, NUM_PING, 1000, 10000, size, cb_ping6, pico_ipv6_source_dev_find(&dst));
|
||||
#endif
|
||||
if (timeout > 0) {
|
||||
printf("Adding abort timer after %d seconds for id %d\n", timeout, id);
|
||||
if (!pico_timer_add(timeout * 1000, ping_abort_timer, &id)) {
|
||||
printf("Failed to set ping abort timeout, aborting ping\n");
|
||||
ping_abort_timer((pico_time)0, &id);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* free copied args */
|
||||
if (dest)
|
||||
free(dest);
|
||||
|
||||
if (abort)
|
||||
free(abort);
|
||||
}
|
||||
#endif
|
||||
/*** END PING ***/
|
||||
|
||||
72
kernel/picotcp/test/examples/slaacv4.c
Normal file
72
kernel/picotcp/test/examples/slaacv4.c
Normal file
@ -0,0 +1,72 @@
|
||||
#include "utils.h"
|
||||
#include <pico_slaacv4.h>
|
||||
#include <pico_icmp4.h>
|
||||
/*** START SLAACV4 ***/
|
||||
|
||||
void ping_callback_slaacv4(struct pico_icmp4_stats *s)
|
||||
{
|
||||
char host[30] = { };
|
||||
|
||||
pico_ipv4_to_string(host, s->dst.addr);
|
||||
if (s->err == 0) {
|
||||
dbg("SLAACV4: %lu bytes from %s: icmp_req=%lu ttl=64 time=%lu ms\n", s->size, host,
|
||||
s->seq, (long unsigned int)s->time);
|
||||
if (s->seq >= 3) {
|
||||
dbg("SLAACV4: TEST SUCCESS!\n");
|
||||
pico_slaacv4_unregisterip();
|
||||
exit(0);
|
||||
}
|
||||
} else {
|
||||
dbg("SLAACV4: ping %lu to %s error %d\n", s->seq, host, s->err);
|
||||
dbg("SLAACV4: TEST FAILED!\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void slaacv4_cb(struct pico_ip4 *ip, uint8_t code)
|
||||
{
|
||||
char dst[16] = "169.254.22.5";
|
||||
printf("SLAACV4 CALLBACK ip:0x%X code:%d \n", ip->addr, code);
|
||||
if (code == 0)
|
||||
{
|
||||
#ifdef PICO_SUPPORT_PING
|
||||
pico_icmp4_ping(dst, 3, 1000, 5000, 32, ping_callback_slaacv4);
|
||||
#else
|
||||
exit(0);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
exit(255);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void app_slaacv4(char *arg)
|
||||
{
|
||||
char *sdev = NULL;
|
||||
char *nxt = arg;
|
||||
struct pico_device *dev = NULL;
|
||||
|
||||
if (!nxt)
|
||||
exit(255);
|
||||
|
||||
while (nxt) {
|
||||
if (nxt) {
|
||||
nxt = cpy_arg(&sdev, nxt);
|
||||
if(!sdev) {
|
||||
exit(255);
|
||||
}
|
||||
}
|
||||
}
|
||||
dev = pico_get_device(sdev);
|
||||
free(sdev);
|
||||
if(dev == NULL) {
|
||||
printf("%s: error getting device %s: %s\n", __FUNCTION__, dev->name, strerror(pico_err));
|
||||
exit(255);
|
||||
}
|
||||
|
||||
pico_slaacv4_claimip(dev, slaacv4_cb);
|
||||
}
|
||||
/*** END SLAACv4 ***/
|
||||
59
kernel/picotcp/test/examples/sntp.c
Normal file
59
kernel/picotcp/test/examples/sntp.c
Normal file
@ -0,0 +1,59 @@
|
||||
#include "utils.h"
|
||||
#include <pico_sntp_client.h>
|
||||
/*** START SNTP ***/
|
||||
|
||||
#ifdef PICO_SUPPORT_SNTP_CLIENT
|
||||
|
||||
void sntp_timeout(pico_time __attribute__((unused)) now, void *arg)
|
||||
{
|
||||
struct pico_timeval ptv;
|
||||
struct timeval tv;
|
||||
pico_sntp_gettimeofday(&ptv);
|
||||
gettimeofday(&tv, NULL);
|
||||
printf("Linux sec: %u, msec: %u\n", (unsigned int)tv.tv_sec, (unsigned int)tv.tv_usec / 1000);
|
||||
printf("Picotcp sec: %u, msec: %u\n", (unsigned int)ptv.tv_sec, (unsigned int)ptv.tv_msec);
|
||||
printf("SNTP test succesfull!\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void cb_synced(pico_err_t status)
|
||||
{
|
||||
if(status == PICO_ERR_ENETDOWN) {
|
||||
printf("SNTP: Cannot resolve ntp server name\n");
|
||||
exit(1);
|
||||
} else if (status == PICO_ERR_ETIMEDOUT) {
|
||||
printf("SNTP: Timed out, did not receive ntp packet from server\n");
|
||||
exit(1);
|
||||
} else if (status == PICO_ERR_EINVAL) {
|
||||
printf("SNTP: Conversion error\n");
|
||||
exit(1);
|
||||
} else if (status == PICO_ERR_ENOTCONN) {
|
||||
printf("SNTP: Socket error\n");
|
||||
exit(1);
|
||||
} else if (status == PICO_ERR_NOERR) {
|
||||
if (!pico_timer_add(2000, sntp_timeout, NULL)) {
|
||||
printf("SNTP: Failed to start timeout timer, exiting program \n");
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
printf("SNTP: Invalid status received in cb_synced\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void app_sntp(char *servername)
|
||||
{
|
||||
struct pico_timeval tv;
|
||||
printf("Starting SNTP query towards %s\n", servername);
|
||||
if(pico_sntp_gettimeofday(&tv) == 0)
|
||||
printf("Wrongly succesfull gettimeofday\n");
|
||||
else
|
||||
printf("Unsuccesfull gettimeofday (not synced)\n");
|
||||
|
||||
if(pico_sntp_sync(servername, &cb_synced) == 0)
|
||||
printf("Succesfull sync call!\n");
|
||||
else
|
||||
printf("Error in sync\n");
|
||||
}
|
||||
#endif
|
||||
/*** END SNTP ***/
|
||||
320
kernel/picotcp/test/examples/tcpbench.c
Normal file
320
kernel/picotcp/test/examples/tcpbench.c
Normal file
@ -0,0 +1,320 @@
|
||||
#include "utils.h"
|
||||
#include <pico_ipv4.h>
|
||||
#include <pico_ipv6.h>
|
||||
#include <pico_socket.h>
|
||||
/*** START TCP BENCH ***/
|
||||
#define TCP_BENCH_TX 1
|
||||
#define TCP_BENCH_RX 2
|
||||
#define TCP_BENCH_TX_FOREVER 3
|
||||
static char *buffer1;
|
||||
static char *buffer0;
|
||||
|
||||
int tcpbench_mode = 0;
|
||||
struct pico_socket *tcpbench_sock = NULL;
|
||||
static pico_time tcpbench_time_start, tcpbench_time_end;
|
||||
|
||||
void cb_tcpbench(uint16_t ev, struct pico_socket *s)
|
||||
{
|
||||
static int closed = 0;
|
||||
static unsigned long count = 0;
|
||||
uint8_t recvbuf[1500];
|
||||
uint16_t port;
|
||||
char peer[200];
|
||||
/* struct pico_socket *sock_a; */
|
||||
|
||||
static int tcpbench_wr_size = 0;
|
||||
static int tcpbench_rd_size = 0;
|
||||
int tcpbench_w = 0;
|
||||
int tcpbench_r = 0;
|
||||
double tcpbench_time = 0;
|
||||
|
||||
count++;
|
||||
|
||||
if (ev & PICO_SOCK_EV_RD) {
|
||||
do {
|
||||
/* read data, but discard */
|
||||
tcpbench_r = pico_socket_read(s, recvbuf, 1500);
|
||||
if (tcpbench_r > 0) {
|
||||
tcpbench_rd_size += tcpbench_r;
|
||||
}
|
||||
} while (tcpbench_r > 0);
|
||||
if (tcpbench_time_start == 0)
|
||||
tcpbench_time_start = PICO_TIME_MS();
|
||||
|
||||
printf("tcpbench_rd_size = %d \r", tcpbench_rd_size);
|
||||
}
|
||||
|
||||
if (ev & PICO_SOCK_EV_CONN) {
|
||||
if (!IPV6_MODE) {
|
||||
struct pico_ip4 orig;
|
||||
if (tcpbench_mode == TCP_BENCH_TX || tcpbench_mode == TCP_BENCH_TX_FOREVER) {
|
||||
printf("tcpbench> Connection established with server.\n");
|
||||
} else if (tcpbench_mode == TCP_BENCH_RX) {
|
||||
/* sock_a = pico_socket_accept(s, &orig, &port); */
|
||||
pico_socket_accept(s, &orig, &port);
|
||||
pico_ipv4_to_string(peer, orig.addr);
|
||||
printf("tcpbench> Connection established with %s:%d.\n", peer, short_be(port));
|
||||
}
|
||||
} else {
|
||||
struct pico_ip6 orig;
|
||||
if (tcpbench_mode == TCP_BENCH_TX || tcpbench_mode == TCP_BENCH_TX_FOREVER) {
|
||||
printf("tcpbench> Connection established with server.\n");
|
||||
} else if (tcpbench_mode == TCP_BENCH_RX) {
|
||||
/* sock_a = pico_socket_accept(s, &orig, &port); */
|
||||
pico_socket_accept(s, &orig, &port);
|
||||
#ifdef PICO_SUPPORT_IPV6
|
||||
pico_ipv6_to_string(peer, orig.addr);
|
||||
printf("tcpbench> Connection established with [%s]:%d.\n", peer, short_be(port));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ev & PICO_SOCK_EV_FIN) {
|
||||
printf("tcpbench> Socket closed. Exit normally. \n");
|
||||
if (tcpbench_mode == TCP_BENCH_RX) {
|
||||
tcpbench_time_end = PICO_TIME_MS();
|
||||
tcpbench_time = (tcpbench_time_end - tcpbench_time_start) / 1000.0; /* get number of seconds */
|
||||
printf("tcpbench> received %d bytes in %lf seconds\n", tcpbench_rd_size, tcpbench_time);
|
||||
printf("tcpbench> average read throughput %lf kbit/sec\n", ((tcpbench_rd_size * 8.0) / tcpbench_time) / 1000);
|
||||
pico_socket_shutdown(s, PICO_SHUT_WR);
|
||||
printf("tcpbench> Called shutdown write, ev = %d\n", ev);
|
||||
}
|
||||
|
||||
if (!pico_timer_add(5000, deferred_exit, NULL)) {
|
||||
printf("tcpbench> Failed to start exit timer, exiting now\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (ev & PICO_SOCK_EV_ERR) {
|
||||
printf("tcpbench> ---- Socket Error received: %s. Bailing out.\n", strerror(pico_err));
|
||||
if (!pico_err == PICO_ERR_ECONNRESET) {
|
||||
if (pico_timer_add(5000, deferred_exit, NULL)) {
|
||||
printf("tcpbench> Failed to start exit timer, exiting now\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
printf("tcpbench> ---- Socket Error: '%s'. Was unexpected! Something went wrong.\n", strerror(pico_err));
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
|
||||
if (ev & PICO_SOCK_EV_CLOSE) {
|
||||
printf("tcpbench> event close\n");
|
||||
if (tcpbench_mode == TCP_BENCH_RX) {
|
||||
pico_socket_close(s);
|
||||
printf("tcpbench> Called shutdown write, ev = %d\n", ev);
|
||||
} else if (tcpbench_mode == TCP_BENCH_TX || tcpbench_mode == TCP_BENCH_TX_FOREVER) {
|
||||
pico_socket_close(s);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (ev & PICO_SOCK_EV_WR) {
|
||||
if (((tcpbench_wr_size < TCPSIZ) && (tcpbench_mode == TCP_BENCH_TX)) || tcpbench_mode == TCP_BENCH_TX_FOREVER) {
|
||||
do {
|
||||
tcpbench_w = pico_socket_write(tcpbench_sock, buffer0 + (tcpbench_wr_size % TCPSIZ), TCPSIZ - (tcpbench_wr_size % TCPSIZ));
|
||||
if (tcpbench_w > 0) {
|
||||
tcpbench_wr_size += tcpbench_w;
|
||||
/* printf("tcpbench> SOCKET WRITTEN - %d\n",tcpbench_w); */
|
||||
} else {
|
||||
/* printf("pico_socket_write returned %d\n", tcpbench_w); */
|
||||
}
|
||||
|
||||
if (tcpbench_time_start == 0)
|
||||
tcpbench_time_start = PICO_TIME_MS();
|
||||
} while(tcpbench_w > 0);
|
||||
printf("tcpbench_wr_size = %d \r", tcpbench_wr_size);
|
||||
} else {
|
||||
if (!closed && tcpbench_mode == TCP_BENCH_TX) {
|
||||
tcpbench_time_end = PICO_TIME_MS();
|
||||
pico_socket_shutdown(s, PICO_SHUT_WR);
|
||||
printf("tcpbench> TCPSIZ written\n");
|
||||
printf("tcpbench> Called shutdown()\n");
|
||||
tcpbench_time = (tcpbench_time_end - tcpbench_time_start) / 1000.0; /* get number of seconds */
|
||||
printf("tcpbench> Transmitted %u bytes in %lf seconds\n", TCPSIZ, tcpbench_time);
|
||||
printf("tcpbench> average write throughput %lf kbit/sec\n", ((TCPSIZ * 8.0) / tcpbench_time) / 1000);
|
||||
closed = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void app_tcpbench(char *arg)
|
||||
{
|
||||
struct pico_socket *s;
|
||||
char *dport = NULL;
|
||||
char *dest = NULL;
|
||||
char *mode = NULL;
|
||||
char *nagle = NULL;
|
||||
int port = 0, i;
|
||||
uint16_t port_be = 0;
|
||||
char *nxt;
|
||||
char *sport = NULL;
|
||||
int nagle_off = 1;
|
||||
union {
|
||||
struct pico_ip4 ip4;
|
||||
struct pico_ip6 ip6;
|
||||
} inaddr_any = {
|
||||
.ip4 = {0}, .ip6 = {{0}}
|
||||
};
|
||||
|
||||
nxt = cpy_arg(&mode, arg);
|
||||
|
||||
if ((*mode == 't') || (*mode == 'f')) { /* TEST BENCH SEND MODE */
|
||||
if (*mode == 't')
|
||||
tcpbench_mode = TCP_BENCH_TX;
|
||||
else
|
||||
tcpbench_mode = TCP_BENCH_TX_FOREVER;
|
||||
|
||||
printf("tcpbench> TX\n");
|
||||
|
||||
nxt = cpy_arg(&dest, nxt);
|
||||
if (!dest) {
|
||||
fprintf(stderr, "tcpbench send needs the following format: tcpbench:tx:dst_addr[:dport][:n] -- 'n' is for nagle\n");
|
||||
exit(255);
|
||||
}
|
||||
|
||||
printf ("+++ Dest is %s\n", dest);
|
||||
if (nxt) {
|
||||
printf("Next arg: %s\n", nxt);
|
||||
nxt = cpy_arg(&dport, nxt);
|
||||
printf("Dport: %s\n", dport);
|
||||
}
|
||||
|
||||
if (nxt) {
|
||||
printf("Next arg: %s\n", nxt);
|
||||
nxt = cpy_arg(&nagle, nxt);
|
||||
printf("nagle: %s\n", nagle);
|
||||
if (strlen(nagle) == 1 && nagle[0] == 'n') {
|
||||
nagle_off = 0;
|
||||
printf("Nagle algorithm enabled\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (dport) {
|
||||
port = atoi(dport);
|
||||
port_be = short_be((uint16_t)port);
|
||||
}
|
||||
|
||||
if (port == 0) {
|
||||
port_be = short_be(5555);
|
||||
}
|
||||
|
||||
buffer0 = malloc(TCPSIZ);
|
||||
buffer1 = malloc(TCPSIZ);
|
||||
printf("Buffer1 (%p)\n", buffer1);
|
||||
for (i = 0; i < TCPSIZ; i++) {
|
||||
char c = (i % 26) + 'a';
|
||||
buffer0[i] = c;
|
||||
}
|
||||
memset(buffer1, 'a', TCPSIZ);
|
||||
printf("tcpbench> Connecting to: %s:%d\n", dest, short_be(port_be));
|
||||
|
||||
if (!IPV6_MODE) {
|
||||
struct pico_ip4 server_addr;
|
||||
s = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_TCP, &cb_tcpbench);
|
||||
if (!s)
|
||||
exit(1);
|
||||
|
||||
pico_socket_setoption(s, PICO_TCP_NODELAY, &nagle_off);
|
||||
|
||||
/* NOTE: used to set a fixed local port and address
|
||||
local_port = short_be(6666);
|
||||
pico_string_to_ipv4("10.40.0.11", &local_addr.addr);
|
||||
pico_socket_bind(s, &local_addr, &local_port);*/
|
||||
|
||||
pico_string_to_ipv4(dest, &server_addr.addr);
|
||||
pico_socket_connect(s, &server_addr, port_be);
|
||||
} else {
|
||||
struct pico_ip6 server_addr;
|
||||
s = pico_socket_open(PICO_PROTO_IPV6, PICO_PROTO_TCP, &cb_tcpbench);
|
||||
if (!s)
|
||||
exit(1);
|
||||
|
||||
pico_socket_setoption(s, PICO_TCP_NODELAY, &nagle_off);
|
||||
|
||||
/* NOTE: used to set a fixed local port and address
|
||||
local_port = short_be(6666);
|
||||
pico_string_to_ipv4("10.40.0.11", &local_addr.addr);
|
||||
pico_socket_bind(s, &local_addr, &local_port);*/
|
||||
#ifdef PICO_SUPPORT_IPV6
|
||||
pico_string_to_ipv6(dest, server_addr.addr);
|
||||
pico_socket_connect(s, &server_addr, port_be);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
} else if (*mode == 'r') { /* TEST BENCH RECEIVE MODE */
|
||||
int ret;
|
||||
tcpbench_mode = TCP_BENCH_RX;
|
||||
printf("tcpbench> RX\n");
|
||||
|
||||
cpy_arg(&sport, nxt);
|
||||
if (!sport) {
|
||||
fprintf(stderr, "tcpbench receive needs the following format: tcpbench:rx[:dport]\n");
|
||||
exit(255);
|
||||
}
|
||||
|
||||
if (sport) {
|
||||
printf("s-port is %s\n", sport);
|
||||
port = atoi(sport);
|
||||
port_be = short_be((uint16_t)port);
|
||||
printf("tcpbench> Got port %d\n", port);
|
||||
free(sport);
|
||||
}
|
||||
|
||||
if (port == 0) {
|
||||
port_be = short_be(5555);
|
||||
}
|
||||
|
||||
printf("tcpbench> OPEN\n");
|
||||
if (!IPV6_MODE)
|
||||
s = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_TCP, &cb_tcpbench);
|
||||
else
|
||||
s = pico_socket_open(PICO_PROTO_IPV6, PICO_PROTO_TCP, &cb_tcpbench);
|
||||
|
||||
if (!s)
|
||||
exit(1);
|
||||
|
||||
printf("tcpbench> BIND\n");
|
||||
if (!IPV6_MODE)
|
||||
ret = pico_socket_bind(s, &inaddr_any.ip4, &port_be);
|
||||
else
|
||||
ret = pico_socket_bind(s, &inaddr_any.ip6, &port_be);
|
||||
|
||||
if (ret < 0) {
|
||||
printf("tcpbench> BIND failed because %s\n", strerror(pico_err));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf("tcpbench> LISTEN\n");
|
||||
if (pico_socket_listen(s, 40) != 0)
|
||||
exit(1);
|
||||
|
||||
printf("tcpbench> listening port %u ...\n", short_be(port_be));
|
||||
} else {
|
||||
printf("tcpbench> wrong mode argument\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
tcpbench_sock = s;
|
||||
|
||||
/* free strdups */
|
||||
if (dport)
|
||||
free(dport);
|
||||
|
||||
if (dest)
|
||||
free (dest);
|
||||
|
||||
if (mode)
|
||||
free (mode);
|
||||
|
||||
if (nagle)
|
||||
free (nagle);
|
||||
|
||||
return;
|
||||
}
|
||||
/*** END TCP BENCH ***/
|
||||
197
kernel/picotcp/test/examples/tcpclient.c
Normal file
197
kernel/picotcp/test/examples/tcpclient.c
Normal file
@ -0,0 +1,197 @@
|
||||
#include "utils.h"
|
||||
#include <pico_ipv4.h>
|
||||
#include <pico_ipv6.h>
|
||||
#include <pico_socket.h>
|
||||
/*** START TCP CLIENT ***/
|
||||
static char *buffer1;
|
||||
static char *buffer0;
|
||||
|
||||
void compare_results(pico_time __attribute__((unused)) now, void __attribute__((unused)) *arg)
|
||||
{
|
||||
#ifdef CONSISTENCY_CHECK /* TODO: Enable */
|
||||
int i;
|
||||
printf("Calculating result.... (%p)\n", buffer1);
|
||||
|
||||
if (memcmp(buffer0, buffer1, TCPSIZ) == 0)
|
||||
exit(0);
|
||||
|
||||
for (i = 0; i < TCPSIZ; i++) {
|
||||
if (buffer0[i] != buffer1[i]) {
|
||||
fprintf(stderr, "Error at byte %d - %c!=%c\n", i, buffer0[i], buffer1[i]);
|
||||
exit(115);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
exit(0);
|
||||
|
||||
}
|
||||
|
||||
void cb_tcpclient(uint16_t ev, struct pico_socket *s)
|
||||
{
|
||||
static int w_size = 0;
|
||||
static int r_size = 0;
|
||||
static int closed = 0;
|
||||
int r, w;
|
||||
static unsigned long count = 0;
|
||||
|
||||
count++;
|
||||
picoapp_dbg("tcpclient> wakeup %lu, event %u\n", count, ev);
|
||||
|
||||
if (ev & PICO_SOCK_EV_RD) {
|
||||
do {
|
||||
r = pico_socket_read(s, buffer1 + r_size, TCPSIZ - r_size);
|
||||
if (r > 0) {
|
||||
r_size += r;
|
||||
picoapp_dbg("SOCKET READ - %d\n", r_size);
|
||||
}
|
||||
|
||||
if (r < 0)
|
||||
exit(5);
|
||||
} while(r > 0);
|
||||
}
|
||||
|
||||
if (ev & PICO_SOCK_EV_CONN) {
|
||||
printf("Connection established with server.\n");
|
||||
}
|
||||
|
||||
if (ev & PICO_SOCK_EV_FIN) {
|
||||
printf("Socket closed. Exit normally. \n");
|
||||
if (!pico_timer_add(2000, compare_results, NULL)) {
|
||||
printf("Failed to start exit timer, exiting now\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (ev & PICO_SOCK_EV_ERR) {
|
||||
printf("Socket error received: %s. Bailing out.\n", strerror(pico_err));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (ev & PICO_SOCK_EV_CLOSE) {
|
||||
printf("Socket received close from peer - Wrong case if not all client data sent!\n");
|
||||
pico_socket_close(s);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ev & PICO_SOCK_EV_WR) {
|
||||
if (w_size < TCPSIZ) {
|
||||
do {
|
||||
w = pico_socket_write(s, buffer0 + w_size, TCPSIZ - w_size);
|
||||
if (w > 0) {
|
||||
w_size += w;
|
||||
picoapp_dbg("SOCKET WRITTEN - %d\n", w_size);
|
||||
if (w < 0)
|
||||
exit(5);
|
||||
}
|
||||
} while(w > 0);
|
||||
} else {
|
||||
#ifdef INFINITE_TCPTEST
|
||||
w_size = 0;
|
||||
return;
|
||||
#endif
|
||||
if (!closed) {
|
||||
pico_socket_shutdown(s, PICO_SHUT_WR);
|
||||
printf("Called shutdown()\n");
|
||||
closed = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void app_tcpclient(char *arg)
|
||||
{
|
||||
char *daddr = NULL, *dport = NULL;
|
||||
char *nxt = arg;
|
||||
uint16_t send_port = 0, listen_port = short_be(5555);
|
||||
int i = 0, ret = 0, yes = 1;
|
||||
struct pico_socket *s = NULL;
|
||||
union pico_address dst = {
|
||||
.ip4 = {0}, .ip6 = {{0}}
|
||||
};
|
||||
union pico_address inaddr_any = {
|
||||
.ip4 = {0}, .ip6 = {{0}}
|
||||
};
|
||||
|
||||
/* start of argument parsing */
|
||||
if (nxt) {
|
||||
nxt = cpy_arg(&daddr, arg);
|
||||
if (daddr) {
|
||||
if (!IPV6_MODE)
|
||||
pico_string_to_ipv4(daddr, &dst.ip4.addr);
|
||||
|
||||
#ifdef PICO_SUPPORT_IPV6
|
||||
else
|
||||
pico_string_to_ipv6(daddr, dst.ip6.addr);
|
||||
#endif
|
||||
} else {
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
/* missing dest_addr */
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (nxt) {
|
||||
nxt = cpy_arg(&dport, nxt);
|
||||
if (dport && atoi(dport)) {
|
||||
send_port = short_be(atoi(dport));
|
||||
} else {
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
/* missing send_port */
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* end of argument parsing */
|
||||
|
||||
buffer0 = malloc(TCPSIZ);
|
||||
buffer1 = malloc(TCPSIZ);
|
||||
printf("Buffer1 (%p)\n", buffer1);
|
||||
for (i = 0; i < TCPSIZ; i++) {
|
||||
char c = (i % 26) + 'a';
|
||||
buffer0[i] = c;
|
||||
}
|
||||
memset(buffer1, 'a', TCPSIZ);
|
||||
|
||||
printf("Connecting to: %s:%d\n", daddr, short_be(send_port));
|
||||
|
||||
if (!IPV6_MODE)
|
||||
s = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_TCP, &cb_tcpclient);
|
||||
else
|
||||
s = pico_socket_open(PICO_PROTO_IPV6, PICO_PROTO_TCP, &cb_tcpclient);
|
||||
|
||||
if (!s) {
|
||||
printf("%s: error opening socket: %s\n", __FUNCTION__, strerror(pico_err));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
pico_socket_setoption(s, PICO_TCP_NODELAY, &yes);
|
||||
|
||||
if (!IPV6_MODE)
|
||||
ret = pico_socket_bind(s, &inaddr_any.ip4, &listen_port);
|
||||
else
|
||||
ret = pico_socket_bind(s, &inaddr_any.ip6, &listen_port);
|
||||
|
||||
if (ret < 0) {
|
||||
printf("%s: error binding socket to port %u: %s\n", __FUNCTION__, short_be(listen_port), strerror(pico_err));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!IPV6_MODE)
|
||||
ret = pico_socket_connect(s, &dst.ip4, send_port);
|
||||
else
|
||||
ret = pico_socket_connect(s, &dst.ip6, send_port);
|
||||
|
||||
if (ret < 0) {
|
||||
printf("%s: error connecting to %s:%u: %s\n", __FUNCTION__, daddr, short_be(send_port), strerror(pico_err));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
out:
|
||||
fprintf(stderr, "tcpclient expects the following format: tcpclient:dest_addr:dest_port\n");
|
||||
exit(255);
|
||||
}
|
||||
/*** END TCP CLIENT ***/
|
||||
178
kernel/picotcp/test/examples/tcpecho.c
Normal file
178
kernel/picotcp/test/examples/tcpecho.c
Normal file
@ -0,0 +1,178 @@
|
||||
#include "utils.h"
|
||||
#include <pico_socket.h>
|
||||
#include <pico_ipv4.h>
|
||||
/*** START TCP ECHO ***/
|
||||
#define BSIZE (1024 * 10)
|
||||
static char recvbuf[BSIZE];
|
||||
static int pos = 0, len = 0;
|
||||
static int flag = 0;
|
||||
|
||||
int send_tcpecho(struct pico_socket *s)
|
||||
{
|
||||
int w, ww = 0;
|
||||
if (len > pos) {
|
||||
do {
|
||||
w = pico_socket_write(s, recvbuf + pos, len - pos);
|
||||
if (w > 0) {
|
||||
pos += w;
|
||||
ww += w;
|
||||
if (pos >= len) {
|
||||
pos = 0;
|
||||
len = 0;
|
||||
}
|
||||
}
|
||||
} while((w > 0) && (pos < len));
|
||||
}
|
||||
|
||||
return ww;
|
||||
}
|
||||
|
||||
void cb_tcpecho(uint16_t ev, struct pico_socket *s)
|
||||
{
|
||||
int r = 0;
|
||||
|
||||
picoapp_dbg("tcpecho> wakeup ev=%u\n", ev);
|
||||
|
||||
if (ev & PICO_SOCK_EV_RD) {
|
||||
if (flag & PICO_SOCK_EV_CLOSE)
|
||||
printf("SOCKET> EV_RD, FIN RECEIVED\n");
|
||||
|
||||
while (len < BSIZE) {
|
||||
r = pico_socket_read(s, recvbuf + len, BSIZE - len);
|
||||
if (r > 0) {
|
||||
len += r;
|
||||
flag &= ~(PICO_SOCK_EV_RD);
|
||||
} else {
|
||||
flag |= PICO_SOCK_EV_RD;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (flag & PICO_SOCK_EV_WR) {
|
||||
flag &= ~PICO_SOCK_EV_WR;
|
||||
send_tcpecho(s);
|
||||
}
|
||||
}
|
||||
|
||||
if (ev & PICO_SOCK_EV_CONN) {
|
||||
uint32_t ka_val = 0;
|
||||
struct pico_socket *sock_a = {
|
||||
0
|
||||
};
|
||||
struct pico_ip4 orig = {
|
||||
0
|
||||
};
|
||||
uint16_t port = 0;
|
||||
char peer[30] = {
|
||||
0
|
||||
};
|
||||
int yes = 1;
|
||||
|
||||
sock_a = pico_socket_accept(s, &orig, &port);
|
||||
pico_ipv4_to_string(peer, orig.addr);
|
||||
printf("Connection established with %s:%d.\n", peer, short_be(port));
|
||||
pico_socket_setoption(sock_a, PICO_TCP_NODELAY, &yes);
|
||||
/* Set keepalive options */
|
||||
ka_val = 5;
|
||||
pico_socket_setoption(sock_a, PICO_SOCKET_OPT_KEEPCNT, &ka_val);
|
||||
ka_val = 30000;
|
||||
pico_socket_setoption(sock_a, PICO_SOCKET_OPT_KEEPIDLE, &ka_val);
|
||||
ka_val = 5000;
|
||||
pico_socket_setoption(sock_a, PICO_SOCKET_OPT_KEEPINTVL, &ka_val);
|
||||
}
|
||||
|
||||
if (ev & PICO_SOCK_EV_FIN) {
|
||||
printf("Socket closed. Exit normally. \n");
|
||||
if (!pico_timer_add(2000, deferred_exit, NULL)) {
|
||||
printf("Failed to start exit timer, exiting now\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (ev & PICO_SOCK_EV_ERR) {
|
||||
printf("Socket error received: %s. Bailing out.\n", strerror(pico_err));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (ev & PICO_SOCK_EV_CLOSE) {
|
||||
printf("Socket received close from peer.\n");
|
||||
if (flag & PICO_SOCK_EV_RD) {
|
||||
pico_socket_shutdown(s, PICO_SHUT_WR);
|
||||
printf("SOCKET> Called shutdown write, ev = %d\n", ev);
|
||||
}
|
||||
}
|
||||
|
||||
if (ev & PICO_SOCK_EV_WR) {
|
||||
r = send_tcpecho(s);
|
||||
if (r == 0)
|
||||
flag |= PICO_SOCK_EV_WR;
|
||||
else
|
||||
flag &= (~PICO_SOCK_EV_WR);
|
||||
}
|
||||
}
|
||||
|
||||
void app_tcpecho(char *arg)
|
||||
{
|
||||
char *nxt = arg;
|
||||
char *lport = NULL;
|
||||
uint16_t listen_port = 0;
|
||||
int ret = 0, yes = 1;
|
||||
struct pico_socket *s = NULL;
|
||||
union {
|
||||
struct pico_ip4 ip4;
|
||||
struct pico_ip6 ip6;
|
||||
} inaddr_any = {
|
||||
.ip4 = {0}, .ip6 = {{0}}
|
||||
};
|
||||
|
||||
/* start of argument parsing */
|
||||
if (nxt) {
|
||||
nxt = cpy_arg(&lport, nxt);
|
||||
if (lport && atoi(lport)) {
|
||||
listen_port = short_be(atoi(lport));
|
||||
} else {
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
/* missing listen_port */
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* end of argument parsing */
|
||||
|
||||
if (!IPV6_MODE)
|
||||
s = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_TCP, &cb_tcpecho);
|
||||
else
|
||||
s = pico_socket_open(PICO_PROTO_IPV6, PICO_PROTO_TCP, &cb_tcpecho);
|
||||
|
||||
if (!s) {
|
||||
printf("%s: error opening socket: %s\n", __FUNCTION__, strerror(pico_err));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
pico_socket_setoption(s, PICO_TCP_NODELAY, &yes);
|
||||
|
||||
|
||||
|
||||
if (!IPV6_MODE)
|
||||
ret = pico_socket_bind(s, &inaddr_any.ip4, &listen_port);
|
||||
else
|
||||
ret = pico_socket_bind(s, &inaddr_any.ip6, &listen_port);
|
||||
|
||||
if (ret < 0) {
|
||||
printf("%s: error binding socket to port %u: %s\n", __FUNCTION__, short_be(listen_port), strerror(pico_err));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (pico_socket_listen(s, 40) != 0) {
|
||||
printf("%s: error listening on port %u\n", __FUNCTION__, short_be(listen_port));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf("Launching PicoTCP echo server\n");
|
||||
return;
|
||||
|
||||
out:
|
||||
fprintf(stderr, "tcpecho expects the following format: tcpecho:listen_port\n");
|
||||
exit(255);
|
||||
}
|
||||
/*** END TCP ECHO ***/
|
||||
485
kernel/picotcp/test/examples/tftp.c
Normal file
485
kernel/picotcp/test/examples/tftp.c
Normal file
@ -0,0 +1,485 @@
|
||||
#include "utils.h"
|
||||
#include <pico_stack.h>
|
||||
#include <pico_tftp.h>
|
||||
#include <pico_ipv4.h>
|
||||
#include <pico_ipv6.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
/* Let's use linux fs */
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
/*** START TFTP ***/
|
||||
#ifdef PICO_SUPPORT_TFTP
|
||||
#define TFTP_MODE_SRV 0
|
||||
#define TFTP_MODE_CLI 1
|
||||
#define TFTP_MODE_PSH 2
|
||||
#define TFTP_TX_COUNT 2000
|
||||
#define TFTP_PAYLOAD_SIZE 512
|
||||
unsigned char tftp_txbuf[TFTP_PAYLOAD_SIZE];
|
||||
static uint16_t family;
|
||||
|
||||
struct command_t {
|
||||
char operation;
|
||||
char *filename;
|
||||
union pico_address server_address;
|
||||
struct command_t *next;
|
||||
};
|
||||
|
||||
struct note_t {
|
||||
char *filename;
|
||||
int fd;
|
||||
char direction;
|
||||
int32_t filesize;
|
||||
struct note_t *next;
|
||||
};
|
||||
|
||||
struct note_t *clipboard = NULL;
|
||||
|
||||
struct note_t *add_note(const char *filename, int fd, char direction)
|
||||
{
|
||||
struct note_t *note = PICO_ZALLOC(sizeof(struct note_t));
|
||||
|
||||
note->filename = strdup(filename);
|
||||
note->fd = fd;
|
||||
note->direction = direction;
|
||||
note->filesize = 0;
|
||||
note->next = clipboard;
|
||||
clipboard = note;
|
||||
return note;
|
||||
}
|
||||
|
||||
void del_note(struct note_t *note)
|
||||
{
|
||||
struct note_t *prev;
|
||||
|
||||
if (note == clipboard)
|
||||
{
|
||||
clipboard = clipboard->next;
|
||||
if (note->filename)
|
||||
free (note->filename);
|
||||
|
||||
PICO_FREE(note);
|
||||
} else {
|
||||
for (prev = clipboard; prev->next; prev = prev->next)
|
||||
if (prev->next == note) {
|
||||
prev->next = note->next;
|
||||
if (note->filename)
|
||||
free (note->filename);
|
||||
|
||||
PICO_FREE(note);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
struct command_t *add_command(struct command_t *commands, char operation,
|
||||
char *filename, union pico_address *server_address)
|
||||
{
|
||||
struct command_t *command = PICO_ZALLOC(sizeof(struct command_t));
|
||||
|
||||
command->operation = operation;
|
||||
command->filename = filename;
|
||||
memcpy(&command->server_address, server_address, sizeof(union pico_address));
|
||||
command->next = commands;
|
||||
return command;
|
||||
}
|
||||
|
||||
int32_t get_filesize(const char *filename)
|
||||
{
|
||||
int ret;
|
||||
struct stat buf;
|
||||
|
||||
ret = stat(filename, &buf);
|
||||
if (ret)
|
||||
return -1;
|
||||
|
||||
return buf.st_size;
|
||||
}
|
||||
|
||||
struct note_t *setup_transfer(char operation, const char *filename)
|
||||
{
|
||||
int fd;
|
||||
|
||||
printf("operation %c\n", operation);
|
||||
fd = open(filename, (toupper(operation) == 'T') ? O_RDONLY : O_WRONLY | O_EXCL | O_CREAT, 0666);
|
||||
if (fd < 0) {
|
||||
perror("open");
|
||||
fprintf(stderr, "Unable to handle file %s\n", filename);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return add_note(filename, fd, operation);
|
||||
}
|
||||
|
||||
int cb_tftp_tx(struct pico_tftp_session *session, uint16_t event, uint8_t *block, int32_t len, void *arg)
|
||||
{
|
||||
struct note_t *note = (struct note_t *) arg;
|
||||
|
||||
if (event != PICO_TFTP_EV_OK) {
|
||||
fprintf(stderr, "TFTP: Error %" PRIu16 ": %s\n", event, block);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
len = read(note->fd, tftp_txbuf, PICO_TFTP_PAYLOAD_SIZE);
|
||||
|
||||
if (len >= 0) {
|
||||
note->filesize += len;
|
||||
pico_tftp_send(session, tftp_txbuf, len);
|
||||
if (len < PICO_TFTP_PAYLOAD_SIZE) {
|
||||
printf("TFTP: file %s (%" PRId32 " bytes) TX transfer complete!\n", note->filename, note->filesize);
|
||||
close(note->fd);
|
||||
del_note(note);
|
||||
}
|
||||
} else {
|
||||
perror("read");
|
||||
fprintf(stderr, "Filesystem error reading file %s, cancelling current transfer\n", note->filename);
|
||||
pico_tftp_abort(session, TFTP_ERR_EACC, "Error on read");
|
||||
del_note(note);
|
||||
}
|
||||
|
||||
if (!clipboard) {
|
||||
if (!pico_timer_add(3000, deferred_exit, NULL)) {
|
||||
printf("Failed to start exit timer, exiting now\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
int cb_tftp_tx_opt(struct pico_tftp_session *session, uint16_t event, uint8_t *block, int32_t len, void *arg)
|
||||
{
|
||||
int ret;
|
||||
int32_t filesize;
|
||||
|
||||
if (event == PICO_TFTP_EV_OPT) {
|
||||
ret = pico_tftp_get_option(session, PICO_TFTP_OPTION_FILE, &filesize);
|
||||
if (ret)
|
||||
printf("TFTP: Option filesize is not used\n");
|
||||
else
|
||||
printf("TFTP: We expect to transmit %" PRId32 " bytes\n", filesize);
|
||||
|
||||
event = PICO_TFTP_EV_OK;
|
||||
}
|
||||
|
||||
return cb_tftp_tx(session, event, block, len, arg);
|
||||
}
|
||||
|
||||
int cb_tftp_rx(struct pico_tftp_session *session, uint16_t event, uint8_t *block, int32_t len, void *arg)
|
||||
{
|
||||
struct note_t *note = (struct note_t *) arg;
|
||||
int ret;
|
||||
|
||||
if (event != PICO_TFTP_EV_OK) {
|
||||
fprintf(stderr, "TFTP: Error %" PRIu16 ": %s\n", event, block);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!note)
|
||||
return 0;
|
||||
|
||||
note->filesize += len;
|
||||
if (write(note->fd, block, len) < 0) {
|
||||
perror("write");
|
||||
fprintf(stderr, "Filesystem error writing file %s, cancelling current transfer\n", note->filename);
|
||||
pico_tftp_abort(session, TFTP_ERR_EACC, "Error on write");
|
||||
del_note(note);
|
||||
} else {
|
||||
if (len != PICO_TFTP_PAYLOAD_SIZE) {
|
||||
printf("TFTP: file %s (%" PRId32 " bytes) RX transfer complete!\n", note->filename, note->filesize);
|
||||
close(note->fd);
|
||||
del_note(note);
|
||||
}
|
||||
}
|
||||
|
||||
if (!clipboard) {
|
||||
if (!pico_timer_add(3000, deferred_exit, NULL)) {
|
||||
printf("Failed to start exit timer, exiting now\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
int cb_tftp_rx_opt(struct pico_tftp_session *session, uint16_t event, uint8_t *block, int32_t len, void *arg)
|
||||
{
|
||||
int ret;
|
||||
int32_t filesize;
|
||||
|
||||
if (event == PICO_TFTP_EV_OPT) {
|
||||
ret = pico_tftp_get_option(session, PICO_TFTP_OPTION_FILE, &filesize);
|
||||
if (ret)
|
||||
printf("TFTP: Option filesize is not used\n");
|
||||
else
|
||||
printf("TFTP: We expect to receive %" PRId32 " bytes\n", filesize);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return cb_tftp_rx(session, event, block, len, arg);
|
||||
}
|
||||
|
||||
struct pico_tftp_session *make_session_or_die(union pico_address *addr, uint16_t family)
|
||||
{
|
||||
struct pico_tftp_session *session;
|
||||
|
||||
session = pico_tftp_session_setup(addr, family);
|
||||
if (!session) {
|
||||
fprintf(stderr, "TFTP: Error in session setup\n");
|
||||
exit(3);
|
||||
}
|
||||
|
||||
return session;
|
||||
}
|
||||
|
||||
struct note_t *transfer_prepare(struct pico_tftp_session **psession, char operation, const char *filename, union pico_address *addr, uint16_t family)
|
||||
{
|
||||
struct note_t *note;
|
||||
|
||||
note = setup_transfer(operation, filename);
|
||||
*psession = make_session_or_die(addr, family);
|
||||
return note;
|
||||
}
|
||||
|
||||
void start_rx(struct pico_tftp_session *session, const char *filename, uint16_t port,
|
||||
int (*rx_callback)(struct pico_tftp_session *session, uint16_t err, uint8_t *block, int32_t len, void *arg),
|
||||
struct note_t *note)
|
||||
{
|
||||
if (pico_tftp_start_rx(session, port, filename, rx_callback, note)) {
|
||||
fprintf(stderr, "TFTP: Error in initialization\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void start_tx(struct pico_tftp_session *session, const char *filename, uint16_t port,
|
||||
int (*tx_callback)(struct pico_tftp_session *session, uint16_t err, uint8_t *block, int32_t len, void *arg),
|
||||
struct note_t *note)
|
||||
{
|
||||
if (pico_tftp_start_tx(session, port, filename, tx_callback, note)) {
|
||||
fprintf(stderr, "TFTP: Error in initialization\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void tftp_listen_cb(union pico_address *addr, uint16_t port, uint16_t opcode, char *filename, int32_t len)
|
||||
{
|
||||
struct note_t *note;
|
||||
struct pico_tftp_session *session;
|
||||
|
||||
printf("TFTP listen callback (BASIC) from remote port %" PRIu16 ".\n", short_be(port));
|
||||
if (opcode == PICO_TFTP_RRQ) {
|
||||
printf("Received TFTP get request for %s\n", filename);
|
||||
note = transfer_prepare(&session, 't', filename, addr, family);
|
||||
start_tx(session, filename, port, cb_tftp_tx, note);
|
||||
} else if (opcode == PICO_TFTP_WRQ) {
|
||||
printf("Received TFTP put request for %s\n", filename);
|
||||
note = transfer_prepare(&session, 'r', filename, addr, family);
|
||||
start_rx(session, filename, port, cb_tftp_rx, note);
|
||||
}
|
||||
}
|
||||
|
||||
void tftp_listen_cb_opt(union pico_address *addr, uint16_t port, uint16_t opcode, char *filename, int32_t len)
|
||||
{
|
||||
struct note_t *note;
|
||||
struct pico_tftp_session *session;
|
||||
int options;
|
||||
uint8_t timeout;
|
||||
int32_t filesize;
|
||||
int ret;
|
||||
|
||||
printf("TFTP listen callback (OPTIONS) from remote port %" PRIu16 ".\n", short_be(port));
|
||||
/* declare the options we want to support */
|
||||
ret = pico_tftp_parse_request_args(filename, len, &options, &timeout, &filesize);
|
||||
if (ret)
|
||||
pico_tftp_reject_request(addr, port, TFTP_ERR_EOPT, "Malformed request");
|
||||
|
||||
if (opcode == PICO_TFTP_RRQ) {
|
||||
printf("Received TFTP get request for %s\n", filename);
|
||||
note = transfer_prepare(&session, 'T', filename, addr, family);
|
||||
|
||||
if (options & PICO_TFTP_OPTION_TIME)
|
||||
pico_tftp_set_option(session, PICO_TFTP_OPTION_TIME, timeout);
|
||||
|
||||
if (options & PICO_TFTP_OPTION_FILE) {
|
||||
ret = get_filesize(filename);
|
||||
if (ret < 0) {
|
||||
pico_tftp_reject_request(addr, port, TFTP_ERR_ENOENT, "File not found");
|
||||
return;
|
||||
}
|
||||
|
||||
pico_tftp_set_option(session, PICO_TFTP_OPTION_FILE, ret);
|
||||
}
|
||||
|
||||
start_tx(session, filename, port, cb_tftp_tx_opt, note);
|
||||
} else { /* opcode == PICO_TFTP_WRQ */
|
||||
printf("Received TFTP put request for %s\n", filename);
|
||||
|
||||
note = transfer_prepare(&session, 'R', filename, addr, family);
|
||||
if (options & PICO_TFTP_OPTION_TIME)
|
||||
pico_tftp_set_option(session, PICO_TFTP_OPTION_TIME, timeout);
|
||||
|
||||
if (options & PICO_TFTP_OPTION_FILE)
|
||||
pico_tftp_set_option(session, PICO_TFTP_OPTION_FILE, filesize);
|
||||
|
||||
start_rx(session, filename, port, cb_tftp_rx_opt, note);
|
||||
}
|
||||
}
|
||||
|
||||
void print_usage(int exit_code)
|
||||
{
|
||||
printf("\nUsage: tftp:OPTION:[OPTION]...\n"
|
||||
"\nOtions can be repeated. Every option may be one of the following:\n"
|
||||
"\ts\t\t\t starts the basic server (RFC1350)\n"
|
||||
"\tS\t\t\t starts the server with option handling capability\n"
|
||||
"\tt:file:ip\t\t PUT request (without options) for file to server ip\n"
|
||||
"\tT:file:ip\t\t PUT request for file to server ip\n"
|
||||
"\tr:file:ip\t\t GET request (without options) for file to server ip\n"
|
||||
"\tR:file:ip\t\t GET request for file to server ip\n"
|
||||
"Example:\n"
|
||||
"\t\t tftp:S:T:firstFile:10.40.0.2:R:another.file:10.40.0.5:T:secondFile:10.40.0.2\n\n");
|
||||
exit(exit_code);
|
||||
}
|
||||
|
||||
struct command_t *parse_arguments_recursive(struct command_t *commands, char *arg)
|
||||
{
|
||||
char *next;
|
||||
char *operation;
|
||||
char *filename;
|
||||
char *address;
|
||||
static union pico_address remote_address;
|
||||
int ret;
|
||||
struct command_t *new_cmd = NULL;
|
||||
|
||||
if (!arg)
|
||||
return commands;
|
||||
|
||||
next = cpy_arg(&operation, arg);
|
||||
switch (*operation) {
|
||||
case 'S':
|
||||
case 's':
|
||||
filename = address = NULL;
|
||||
break;
|
||||
case 'T':
|
||||
case 'R':
|
||||
case 't':
|
||||
case 'r':
|
||||
if (!next) {
|
||||
fprintf(stderr, "Incomplete client command %s (filename componet is missing)\n", arg);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
next = cpy_arg(&filename, next);
|
||||
if (!next) {
|
||||
fprintf(stderr, "Incomplete client command %s (address component is missing)\n", arg);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
next = cpy_arg(&address, next);
|
||||
if (!IPV6_MODE)
|
||||
ret = pico_string_to_ipv4(address, &remote_address.ip4.addr);
|
||||
else
|
||||
ret = pico_string_to_ipv6(address, remote_address.ip6.addr);
|
||||
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Invalid IP address %s\n", address);
|
||||
print_usage(2);
|
||||
}
|
||||
|
||||
if (address)
|
||||
free(address);
|
||||
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Invalid command %s\n", operation);
|
||||
return NULL;
|
||||
};
|
||||
|
||||
new_cmd = add_command(commands, *operation, filename, &remote_address);
|
||||
free(operation);
|
||||
return parse_arguments_recursive(new_cmd, next);
|
||||
}
|
||||
|
||||
struct command_t *parse_arguments(char *arg)
|
||||
{
|
||||
struct command_t *reversed = parse_arguments_recursive(NULL, arg);
|
||||
struct command_t *commands = NULL;
|
||||
struct command_t *current;
|
||||
|
||||
if (!reversed) {
|
||||
fprintf(stderr, "Wrong command line!\n");
|
||||
print_usage(1);
|
||||
}
|
||||
|
||||
while (reversed) {
|
||||
current = reversed;
|
||||
reversed = reversed->next;
|
||||
current->next = commands;
|
||||
commands = current;
|
||||
}
|
||||
return commands;
|
||||
}
|
||||
|
||||
void app_tftp(char *arg)
|
||||
{
|
||||
struct command_t *commands, *old_cmd;
|
||||
struct note_t *note;
|
||||
struct pico_tftp_session *session;
|
||||
int is_server_enabled = 0;
|
||||
int filesize;
|
||||
|
||||
family = IPV6_MODE ? PICO_PROTO_IPV6 : PICO_PROTO_IPV4;
|
||||
|
||||
commands = parse_arguments(arg);
|
||||
while (commands) {
|
||||
|
||||
if (toupper(commands->operation) != 'S')
|
||||
note = transfer_prepare(&session, commands->operation, commands->filename, &commands->server_address, family);
|
||||
|
||||
switch (commands->operation) {
|
||||
case 'S':
|
||||
case 's':
|
||||
if (!is_server_enabled) {
|
||||
pico_tftp_listen(PICO_PROTO_IPV4, (commands->operation == 'S') ? tftp_listen_cb_opt : tftp_listen_cb);
|
||||
is_server_enabled = 1;
|
||||
}
|
||||
|
||||
break;
|
||||
case 'T':
|
||||
filesize = get_filesize(commands->filename);
|
||||
if (filesize < 0) {
|
||||
fprintf(stderr, "TFTP: unable to read size of file %s\n", commands->filename);
|
||||
exit(3);
|
||||
}
|
||||
|
||||
pico_tftp_set_option(session, PICO_TFTP_OPTION_FILE, filesize);
|
||||
start_tx(session, commands->filename, short_be(PICO_TFTP_PORT), cb_tftp_tx_opt, note);
|
||||
break;
|
||||
case 't':
|
||||
start_tx(session, commands->filename, short_be(PICO_TFTP_PORT), cb_tftp_tx, note);
|
||||
break;
|
||||
case 'R':
|
||||
pico_tftp_set_option(session, PICO_TFTP_OPTION_FILE, 0);
|
||||
start_rx(session, commands->filename, short_be(PICO_TFTP_PORT), cb_tftp_rx_opt, note);
|
||||
break;
|
||||
case 'r':
|
||||
start_rx(session, commands->filename, short_be(PICO_TFTP_PORT), cb_tftp_rx, note);
|
||||
}
|
||||
old_cmd = commands;
|
||||
commands = commands->next;
|
||||
if (old_cmd->filename)
|
||||
free(old_cmd->filename);
|
||||
|
||||
/* commands are allocated using PICO_ZALLOC, so use PICO_FREE */
|
||||
PICO_FREE(old_cmd);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
/* END TFTP */
|
||||
290
kernel/picotcp/test/examples/udp_client.c
Normal file
290
kernel/picotcp/test/examples/udp_client.c
Normal file
@ -0,0 +1,290 @@
|
||||
#include "utils.h"
|
||||
#include <pico_ipv4.h>
|
||||
#include <pico_ipv6.h>
|
||||
#include <pico_socket.h>
|
||||
|
||||
/*** START UDP CLIENT ***/
|
||||
/*
|
||||
* udpclient expects the following format: udpclient:dest_addr:sendto_port[:listen_port:datasize:loops:subloops]
|
||||
* dest_addr: IP address to send datagrams to
|
||||
* sendto_port: port number to send datagrams to
|
||||
* listen_port [OPTIONAL]: port number on which the udpclient listens
|
||||
* datasize [OPTIONAL]: size of the data given to the socket in one go
|
||||
* loops [OPTIONAL]: number of intervals in which data is send
|
||||
* subloops [OPTIONAL]: number of sends in one interval
|
||||
*
|
||||
* REMARK: once an optional parameter is given, all optional parameters need a value!
|
||||
*
|
||||
* f.e.: ./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.40.0.2:255.255.255.0: -a udpclient:10.40.0.3:6667:6667:1400:100:10
|
||||
*/
|
||||
|
||||
struct udpclient_pas *udpclient_pas;
|
||||
|
||||
static int exit_retry = 0;
|
||||
|
||||
static void request_exit_echo(pico_time now, void *arg)
|
||||
{
|
||||
struct pico_socket *s = (struct pico_socket *)arg;
|
||||
char end[4] = "end";
|
||||
pico_socket_send(s, end, 4);
|
||||
if (exit_retry++ > 3) {
|
||||
if (!pico_timer_add(1000, deferred_exit, udpclient_pas)) {
|
||||
printf("Failed to start exit timer, exiting now\n");
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
if (!pico_timer_add(1000, request_exit_echo, s)) {
|
||||
printf("Failed to start request_exit_echo timer, sending request now\n");
|
||||
request_exit_echo((pico_time)0, NULL);
|
||||
exit(1);
|
||||
}
|
||||
printf("%s: requested exit of echo\n", __FUNCTION__);
|
||||
}
|
||||
}
|
||||
|
||||
void udpclient_send(pico_time __attribute__((unused)) now, void __attribute__((unused)) *arg)
|
||||
{
|
||||
struct pico_socket *s = udpclient_pas->s;
|
||||
char *buf = NULL;
|
||||
int i = 0, w = 0;
|
||||
static uint16_t loop = 0;
|
||||
|
||||
if (++loop > udpclient_pas->loops) {
|
||||
if (!pico_timer_add(1000, request_exit_echo, s)) {
|
||||
printf("Failed to start request_exit_echo timer, sending request now\n");
|
||||
request_exit_echo((pico_time)0, NULL);
|
||||
exit(1);
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
buf = calloc(1, udpclient_pas->datasize);
|
||||
if (!buf) {
|
||||
printf("%s: no memory available\n", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
memset(buf, '1', udpclient_pas->datasize);
|
||||
picoapp_dbg("%s: performing loop %u\n", __FUNCTION__, loop);
|
||||
for (i = 0; i < udpclient_pas->subloops; i++) {
|
||||
w = pico_socket_send(s, buf, udpclient_pas->datasize);
|
||||
if (w <= 0)
|
||||
break;
|
||||
}
|
||||
picoapp_dbg("%s: written %u byte(s) in each of %u subloops\n", __FUNCTION__, udpclient_pas->datasize, i);
|
||||
free(buf);
|
||||
}
|
||||
|
||||
if (!pico_timer_add(100, udpclient_send, NULL)) {
|
||||
printf("Failed to start send timer, sending exit request to echo and exiting\n");
|
||||
request_exit_echo((pico_time)0, NULL);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void cb_udpclient(uint16_t ev, struct pico_socket *s)
|
||||
{
|
||||
char *recvbuf = NULL;
|
||||
int r = 0;
|
||||
|
||||
if (ev & PICO_SOCK_EV_RD) {
|
||||
recvbuf = calloc(1, udpclient_pas->datasize);
|
||||
if (!recvbuf) {
|
||||
printf("%s: no memory available\n", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
do {
|
||||
r = pico_socket_recv(s, recvbuf, udpclient_pas->datasize);
|
||||
} while ( r > 0);
|
||||
free(recvbuf);
|
||||
}
|
||||
|
||||
if (ev == PICO_SOCK_EV_ERR) {
|
||||
printf("Socket Error received. Bailing out.\n");
|
||||
free(udpclient_pas);
|
||||
exit(7);
|
||||
}
|
||||
}
|
||||
|
||||
void app_udpclient(char *arg)
|
||||
{
|
||||
char *daddr = NULL, *lport = NULL, *sport = NULL, *s_datasize = NULL, *s_loops = NULL, *s_subloops = NULL;
|
||||
char *nxt = arg;
|
||||
char sinaddr_any[40] = {
|
||||
0
|
||||
};
|
||||
uint16_t listen_port = 0;
|
||||
int ret = 0;
|
||||
|
||||
udpclient_pas = calloc(1, sizeof(struct udpclient_pas));
|
||||
if (!udpclient_pas) {
|
||||
printf("%s: no memory available\n", __FUNCTION__);
|
||||
exit(255);
|
||||
}
|
||||
|
||||
udpclient_pas->s = NULL;
|
||||
udpclient_pas->loops = 100;
|
||||
udpclient_pas->subloops = 10;
|
||||
udpclient_pas->datasize = 1400;
|
||||
|
||||
/* start of argument parsing */
|
||||
if (nxt) {
|
||||
nxt = cpy_arg(&daddr, arg);
|
||||
if (daddr) {
|
||||
if (!IPV6_MODE)
|
||||
pico_string_to_ipv4(daddr, &udpclient_pas->dst.ip4.addr);
|
||||
|
||||
#ifdef PICO_SUPPORT_IPV6
|
||||
else
|
||||
pico_string_to_ipv6(daddr, udpclient_pas->dst.ip6.addr);
|
||||
#endif
|
||||
} else {
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
/* missing dest_addr */
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (nxt) {
|
||||
nxt = cpy_arg(&sport, nxt);
|
||||
if (sport && atoi(sport)) {
|
||||
udpclient_pas->sport = short_be(atoi(sport));
|
||||
} else {
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
/* missing send_port */
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (nxt) {
|
||||
nxt = cpy_arg(&lport, nxt);
|
||||
if (lport && atoi(lport)) {
|
||||
listen_port = short_be(atoi(lport));
|
||||
} else {
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
/* missing listen_port, use default */
|
||||
listen_port = 0;
|
||||
}
|
||||
|
||||
if (nxt) {
|
||||
nxt = cpy_arg(&s_datasize, nxt);
|
||||
if (s_datasize && atoi(s_datasize)) {
|
||||
udpclient_pas->datasize = atoi(s_datasize);
|
||||
} else {
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
/* missing datasize, incomplete optional parameters? -> exit */
|
||||
if (lport)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (nxt) {
|
||||
nxt = cpy_arg(&s_loops, nxt);
|
||||
if (s_loops && atoi(s_loops)) {
|
||||
udpclient_pas->loops = atoi(s_loops);
|
||||
} else {
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
/* missing loops, incomplete optional parameters? -> exit */
|
||||
if (s_datasize)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (nxt) {
|
||||
nxt = cpy_arg(&s_subloops, nxt);
|
||||
if (s_subloops && atoi(s_subloops)) {
|
||||
udpclient_pas->subloops = atoi(s_subloops);
|
||||
} else {
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
/* missing subloops, incomplete optional parameters? -> exit */
|
||||
if (s_loops)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* end of argument parsing */
|
||||
|
||||
if (!IPV6_MODE)
|
||||
pico_ipv4_to_string(sinaddr_any, inaddr_any.addr);
|
||||
|
||||
#ifdef PICO_SUPPORT_IPV6
|
||||
else
|
||||
pico_ipv6_to_string(sinaddr_any, inaddr6_any.addr);
|
||||
#endif
|
||||
|
||||
if (!IPV6_MODE)
|
||||
udpclient_pas->s = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_UDP, &cb_udpclient);
|
||||
else
|
||||
udpclient_pas->s = pico_socket_open(PICO_PROTO_IPV6, PICO_PROTO_UDP, &cb_udpclient);
|
||||
|
||||
if (!udpclient_pas->s) {
|
||||
printf("%s: error opening socket: %s\n", __FUNCTION__, strerror(pico_err));
|
||||
free(udpclient_pas);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!IPV6_MODE)
|
||||
ret = pico_socket_bind(udpclient_pas->s, &inaddr_any, &listen_port);
|
||||
else
|
||||
ret = pico_socket_bind(udpclient_pas->s, &inaddr6_any, &listen_port);
|
||||
|
||||
if (ret < 0) {
|
||||
free(udpclient_pas);
|
||||
printf("%s: error binding socket to %s:%u: %s\n", __FUNCTION__, sinaddr_any, short_be(listen_port), strerror(pico_err));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!IPV6_MODE)
|
||||
ret = pico_socket_connect(udpclient_pas->s, &udpclient_pas->dst.ip4, udpclient_pas->sport);
|
||||
else
|
||||
ret = pico_socket_connect(udpclient_pas->s, &udpclient_pas->dst.ip6, udpclient_pas->sport);
|
||||
|
||||
if (ret < 0) {
|
||||
printf("%s: error connecting to [%s]:%u: %s\n", __FUNCTION__, daddr, short_be(udpclient_pas->sport), strerror(pico_err));
|
||||
free(udpclient_pas);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf("\n%s: UDP client launched. Sending packets of %u bytes in %u loops and %u subloops to %s:%u\n\n",
|
||||
__FUNCTION__, udpclient_pas->datasize, udpclient_pas->loops, udpclient_pas->subloops, daddr, short_be(udpclient_pas->sport));
|
||||
|
||||
if (!pico_timer_add(100, udpclient_send, NULL)) {
|
||||
printf("Failed to start send timer, sending exit request to echo and exiting\n");
|
||||
request_exit_echo((pico_time)0, NULL);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* free strdups */
|
||||
if (daddr)
|
||||
free (daddr);
|
||||
|
||||
if (lport)
|
||||
free (lport);
|
||||
|
||||
if (sport)
|
||||
free (sport);
|
||||
|
||||
if (s_datasize)
|
||||
free (s_datasize);
|
||||
|
||||
if (s_loops)
|
||||
free (s_loops);
|
||||
|
||||
if (s_subloops)
|
||||
free (s_subloops);
|
||||
|
||||
return;
|
||||
|
||||
out:
|
||||
fprintf(stderr, "udpclient expects the following format: udpclient:dest_addr:dest_port[:listen_port:datasize:loops:subloops]\n");
|
||||
free(udpclient_pas);
|
||||
exit(255);
|
||||
}
|
||||
/*** END UDP CLIENT ***/
|
||||
216
kernel/picotcp/test/examples/udp_echo.c
Normal file
216
kernel/picotcp/test/examples/udp_echo.c
Normal file
@ -0,0 +1,216 @@
|
||||
#include "utils.h"
|
||||
#include <pico_ipv4.h>
|
||||
#include <pico_ipv6.h>
|
||||
#include <pico_socket.h>
|
||||
|
||||
/**** START UDP ECHO ****/
|
||||
/*
|
||||
* udpecho expects the following format: udpecho:bind_addr:listen_port[:sendto_port:datasize]
|
||||
* bind_addr: IP address to bind to
|
||||
* listen_port: port number on which the udpecho listens
|
||||
* sendto_port [OPTIONAL]: port number to echo datagrams to (echo to originating IP address)
|
||||
* datasize [OPTIONAL]: max size of the data red from the socket in one go
|
||||
*
|
||||
* REMARK: once an optional parameter is given, all optional parameters need a value!
|
||||
*
|
||||
* f.e.: ./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.40.0.3:255.255.255.0: -a udpecho:10.40.0.3:6667:6667:1400
|
||||
*/
|
||||
static int udpecho_exit = 0;
|
||||
|
||||
struct udpecho_pas *udpecho_pas;
|
||||
|
||||
void cb_udpecho(uint16_t ev, struct pico_socket *s)
|
||||
{
|
||||
char *recvbuf = NULL;
|
||||
uint16_t port = 0;
|
||||
int r = 0;
|
||||
union {
|
||||
struct pico_ip4 ip4;
|
||||
struct pico_ip6 ip6;
|
||||
} peer;
|
||||
if (udpecho_exit)
|
||||
return;
|
||||
|
||||
if (ev == PICO_SOCK_EV_RD) {
|
||||
recvbuf = calloc(1, udpecho_pas->datasize);
|
||||
if (!recvbuf) {
|
||||
printf("%s: no memory available\n", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
do {
|
||||
r = pico_socket_recvfrom(s, recvbuf, udpecho_pas->datasize, IPV6_MODE ? (void *)peer.ip6.addr : (void *)&peer.ip4.addr, &port);
|
||||
/* printf("UDP recvfrom returned %d\n", r); */
|
||||
if (r > 0) {
|
||||
if (strncmp(recvbuf, "end", 3) == 0) {
|
||||
printf("Client requested to exit... test successful.\n");
|
||||
if (!pico_timer_add(1000, deferred_exit, udpecho_pas)) {
|
||||
printf("Failed to start exit timer, exiting now\n");
|
||||
exit(1);
|
||||
}
|
||||
udpecho_exit++;
|
||||
}
|
||||
|
||||
pico_socket_sendto(s, recvbuf, r, IPV6_MODE ? (void *)peer.ip6.addr : (void *)&peer.ip4.addr, port);
|
||||
}
|
||||
} while (r > 0);
|
||||
free(recvbuf);
|
||||
}
|
||||
|
||||
if (ev == PICO_SOCK_EV_ERR) {
|
||||
printf("Socket Error received. Bailing out.\n");
|
||||
free(udpecho_pas);
|
||||
exit(7);
|
||||
}
|
||||
|
||||
picoapp_dbg("%s: received packet from %08X:%u\n", __FUNCTION__, long_be(peer), short_be(port));
|
||||
}
|
||||
|
||||
void app_udpecho(char *arg)
|
||||
{
|
||||
char *baddr = NULL, *lport = NULL, *sport = NULL, *s_datasize = NULL;
|
||||
char *nxt = arg;
|
||||
uint16_t listen_port = 0;
|
||||
struct pico_ip4 inaddr_bind = { };
|
||||
struct pico_ip6 inaddr_bind6 = { };
|
||||
int ret = 0;
|
||||
|
||||
udpecho_pas = calloc(1, sizeof(struct udpecho_pas));
|
||||
if (!udpecho_pas) {
|
||||
printf("%s: no memory available\n", __FUNCTION__);
|
||||
exit(255);
|
||||
}
|
||||
|
||||
udpecho_pas->s = NULL;
|
||||
udpecho_pas->sendto_port = 0;
|
||||
udpecho_pas->datasize = 5000;
|
||||
|
||||
/* start of argument parsing */
|
||||
if (nxt) {
|
||||
nxt = cpy_arg(&baddr, nxt);
|
||||
if (baddr) {
|
||||
if (!IPV6_MODE)
|
||||
pico_string_to_ipv4(baddr, &inaddr_bind.addr);
|
||||
|
||||
#ifdef PICO_SUPPORT_IPV6
|
||||
else
|
||||
pico_string_to_ipv6(baddr, inaddr_bind6.addr);
|
||||
#endif
|
||||
} else {
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
/* missing bind_addr */
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (nxt) {
|
||||
nxt = cpy_arg(&lport, nxt);
|
||||
if (lport && atoi(lport)) {
|
||||
listen_port = short_be(atoi(lport));
|
||||
} else {
|
||||
listen_port = short_be(5555);
|
||||
}
|
||||
} else {
|
||||
/* missing listen_port */
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (nxt) {
|
||||
nxt = cpy_arg(&sport, nxt);
|
||||
if (sport && atoi(sport)) {
|
||||
udpecho_pas->sendto_port = atoi(sport);
|
||||
} else {
|
||||
/* incorrect send_port */
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
/* missing send_port, use default */
|
||||
}
|
||||
|
||||
if (nxt) {
|
||||
nxt = cpy_arg(&s_datasize, nxt);
|
||||
if (s_datasize && atoi(s_datasize)) {
|
||||
udpecho_pas->datasize = atoi(s_datasize);
|
||||
} else {
|
||||
/* incorrect datasize */
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
/* missing datasize, incomplete optional parameters? -> exit */
|
||||
if (sport)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* end of argument parsing */
|
||||
if (!IPV6_MODE)
|
||||
udpecho_pas->s = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_UDP, &cb_udpecho);
|
||||
else
|
||||
udpecho_pas->s = pico_socket_open(PICO_PROTO_IPV6, PICO_PROTO_UDP, &cb_udpecho);
|
||||
|
||||
if (!udpecho_pas->s) {
|
||||
printf("%s: error opening socket: %s\n", __FUNCTION__, strerror(pico_err));
|
||||
free(udpecho_pas);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!IPV6_MODE)
|
||||
ret = pico_socket_bind(udpecho_pas->s, &inaddr_bind, &listen_port);
|
||||
else {
|
||||
ret = pico_socket_bind(udpecho_pas->s, &inaddr_bind6, &listen_port);
|
||||
printf("udpecho> Bound to [%s]:%d.\n", baddr, short_be(listen_port));
|
||||
}
|
||||
|
||||
if (ret != 0) {
|
||||
free(udpecho_pas);
|
||||
if (!IPV6_MODE)
|
||||
printf("%s: error binding socket to %08X:%u: %s\n", __FUNCTION__, long_be(inaddr_bind.addr), short_be(listen_port), strerror(pico_err));
|
||||
else
|
||||
printf("%s: error binding socket to [%s]:%u: %s\n", __FUNCTION__, baddr, short_be(listen_port), strerror(pico_err));
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#ifdef PICOAPP_IPFILTER
|
||||
{
|
||||
struct pico_ip4 address, in_addr_netmask, in_addr;
|
||||
/* struct pico_ipv4_link *link; */
|
||||
int ret = 0;
|
||||
address.addr = 0x0800280a;
|
||||
in_addr_netmask.addr = 0x00FFFFFF;
|
||||
in_addr.addr = 0x0000320a;
|
||||
/* link = pico_ipv4_link_get(&address); */
|
||||
|
||||
printf("udpecho> IPFILTER ENABLED\n");
|
||||
|
||||
/*Adjust your IPFILTER*/
|
||||
ret |= pico_ipv4_filter_add(NULL, 17, NULL, NULL, &in_addr, &in_addr_netmask, 0, 5555, 0, 0, FILTER_DROP);
|
||||
|
||||
if (ret < 0)
|
||||
printf("Filter_add invalid argument\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
printf("\n%s: UDP echo launched. Receiving packets of %u bytes on port %u\n\n", __FUNCTION__, udpecho_pas->datasize, short_be(listen_port));
|
||||
|
||||
/* free strdups */
|
||||
if (baddr)
|
||||
free (baddr);
|
||||
|
||||
if (lport)
|
||||
free (lport);
|
||||
|
||||
if (sport)
|
||||
free (sport);
|
||||
|
||||
if (s_datasize)
|
||||
free (s_datasize);
|
||||
|
||||
return;
|
||||
|
||||
out:
|
||||
fprintf(stderr, "udpecho expects the following format: udpecho:bind_addr:listen_port[:sendto_port:datasize]\n");
|
||||
free(udpecho_pas);
|
||||
exit(255);
|
||||
}
|
||||
/*** END UDP ECHO ***/
|
||||
88
kernel/picotcp/test/examples/udp_sendto_test.c
Normal file
88
kernel/picotcp/test/examples/udp_sendto_test.c
Normal file
@ -0,0 +1,88 @@
|
||||
#include "utils.h"
|
||||
#include <pico_ipv6.h>
|
||||
#include <pico_socket.h>
|
||||
|
||||
/**** START UDP ECHO ****/
|
||||
/*
|
||||
* udpecho expects the following format: udpecho:bind_addr:listen_port[:sendto_port:datasize]
|
||||
* bind_addr: IP address to bind to
|
||||
* listen_port: port number on which the udpecho listens
|
||||
* sendto_port [OPTIONAL]: port number to echo datagrams to (echo to originating IP address)
|
||||
* datasize [OPTIONAL]: max size of the data red from the socket in one go
|
||||
*
|
||||
* REMARK: once an optional parameter is given, all optional parameters need a value!
|
||||
*
|
||||
* f.e.: ./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.40.0.3:255.255.255.0: -a udpecho:10.40.0.3:6667:6667:1400
|
||||
*/
|
||||
|
||||
void dummy_cb(uint16_t __attribute__((unused)) ev, struct pico_socket __attribute__((unused)) *s)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void app_sendto_test(char *arg)
|
||||
{
|
||||
char *nxt = arg;
|
||||
char *dstaddr = NULL;
|
||||
char *dstport = NULL;
|
||||
struct pico_ip4 inaddr_dst = {};
|
||||
struct pico_ip6 inaddr_dst6 = {};
|
||||
uint16_t dport;
|
||||
struct pico_socket *sock;
|
||||
int ret;
|
||||
|
||||
/* start of argument parsing */
|
||||
if (nxt) {
|
||||
nxt = cpy_arg(&dstaddr, nxt);
|
||||
if (dstaddr) {
|
||||
if (!IPV6_MODE)
|
||||
pico_string_to_ipv4(dstaddr, &inaddr_dst.addr);
|
||||
|
||||
#ifdef PICO_SUPPORT_IPV6
|
||||
else
|
||||
pico_string_to_ipv6(dstaddr, inaddr_dst6.addr);
|
||||
#endif
|
||||
} else {
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
/* missing bind_addr */
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (nxt) {
|
||||
nxt = cpy_arg(&dstport, nxt);
|
||||
if (dstport && atoi(dstport)) {
|
||||
dport = short_be(atoi(dstport));
|
||||
} else {
|
||||
dport = short_be(5555);
|
||||
}
|
||||
} else {
|
||||
/* missing listen_port */
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!IPV6_MODE)
|
||||
sock = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_UDP, &dummy_cb);
|
||||
else
|
||||
sock = pico_socket_open(PICO_PROTO_IPV6, PICO_PROTO_UDP, &dummy_cb);
|
||||
|
||||
ret = pico_socket_sendto(sock, "Testing", 7u, ((IPV6_MODE) ? (void *)(&inaddr_dst6) : (void *)(&inaddr_dst)), dport);
|
||||
if (ret < 0)
|
||||
printf("Failure in first pico_socket_send\n");
|
||||
|
||||
ret = pico_socket_sendto(sock, "Testing", 7u, ((IPV6_MODE) ? (void *)(&inaddr_dst6) : (void *)(&inaddr_dst)), dport);
|
||||
if (ret < 0)
|
||||
printf("Failure in second pico_socket_send\n");
|
||||
|
||||
ret = pico_socket_close(sock);
|
||||
if (ret)
|
||||
printf("Failure in pico_socket_close\n");
|
||||
|
||||
printf("\n%s: UDP sendto test launched. Sending packets to ip %s port %u\n\n", __FUNCTION__, dstaddr, short_be(dport));
|
||||
return;
|
||||
|
||||
out:
|
||||
fprintf(stderr, "udp_sendto_test expects the following format: udp_sendto_test:dest_addr:[dest_por]t\n");
|
||||
exit(255);
|
||||
}
|
||||
151
kernel/picotcp/test/examples/udpnat.c
Normal file
151
kernel/picotcp/test/examples/udpnat.c
Normal file
@ -0,0 +1,151 @@
|
||||
#include "utils.h"
|
||||
#include <pico_ipv6.h>
|
||||
#include <pico_socket.h>
|
||||
|
||||
/*** START UDP NAT CLIENT ***/
|
||||
/* ./build/test/picoapp.elf --vde pic0:/tmp/pic0.ctl:10.40.0.9:255.255.0.0:10.40.0.10: -a udpnatclient:10.50.0.8:6667: */
|
||||
static struct pico_ip4 udpnatclient_inaddr_dst;
|
||||
static uint16_t udpnatclient_port_be;
|
||||
|
||||
void udpnatclient_send(pico_time __attribute__((unused)) now, void *arg)
|
||||
{
|
||||
int i, w;
|
||||
struct pico_socket *s = (struct pico_socket *)arg;
|
||||
char buf[1400] = { };
|
||||
char end[4] = "end";
|
||||
static int loop = 0;
|
||||
|
||||
for ( i = 0; i < 3; i++) {
|
||||
w = pico_socket_send(s, buf, 1400);
|
||||
}
|
||||
if (++loop > 1000) {
|
||||
udpnatclient_port_be = 0;
|
||||
for (i = 0; i < 3; i++) {
|
||||
w = pico_socket_send(s, end, 4);
|
||||
if (w <= 0)
|
||||
break;
|
||||
|
||||
printf("End!\n");
|
||||
}
|
||||
if (!pico_timer_add(1000, deferred_exit, NULL)) {
|
||||
printf("Failed to start exit timer, exiting now\n");
|
||||
exit(1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void cb_udpnatclient(uint16_t ev, struct pico_socket *s)
|
||||
{
|
||||
char recvbuf[1400];
|
||||
int r = 0;
|
||||
|
||||
if (ev & PICO_SOCK_EV_RD) {
|
||||
do {
|
||||
r = pico_socket_recv(s, recvbuf, 1400);
|
||||
} while(r > 0);
|
||||
}
|
||||
|
||||
if (ev == PICO_SOCK_EV_ERR) {
|
||||
printf("Socket Error received. Bailing out.\n");
|
||||
exit(7);
|
||||
}
|
||||
|
||||
/* Not closing to test port check */
|
||||
/* pico_socket_close(s); */
|
||||
}
|
||||
|
||||
void udpnatclient_open_socket(pico_time __attribute__((unused)) now, void __attribute__((unused)) *arg)
|
||||
{
|
||||
struct pico_socket *s = NULL;
|
||||
static int loop;
|
||||
|
||||
if (!udpnatclient_port_be)
|
||||
return;
|
||||
|
||||
loop++;
|
||||
picoapp_dbg(">>>>> Loop %d\n", loop);
|
||||
if (!(loop % 100))
|
||||
printf("Created %d sockets\n", loop);
|
||||
|
||||
s = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_UDP, &cb_udpnatclient);
|
||||
if (!s)
|
||||
exit(1);
|
||||
|
||||
if (pico_socket_connect(s, &udpnatclient_inaddr_dst, udpnatclient_port_be) != 0)
|
||||
{
|
||||
printf("Error connecting\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
picoapp_dbg("New socket with port %u\n", s->local_port);
|
||||
|
||||
if (!pico_timer_add(25, udpnatclient_send, s)) {
|
||||
printf("Failed to start send timer, exiting now\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!pico_timer_add(25, udpnatclient_open_socket, 0)) {
|
||||
printf("Failed to start open_socket timer, exiting now\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void app_udpnatclient(char *arg)
|
||||
{
|
||||
struct pico_socket *s;
|
||||
char *daddr, *dport;
|
||||
int port = 0;
|
||||
uint16_t port_be = 0;
|
||||
struct pico_ip4 inaddr_dst = ZERO_IP4;
|
||||
char *nxt;
|
||||
|
||||
nxt = cpy_arg(&daddr, arg);
|
||||
if (!daddr) {
|
||||
fprintf(stderr, " udpnatclient expects the following format: udpnatclient:dest_addr[:dest_port]\n");
|
||||
exit(255);
|
||||
}
|
||||
|
||||
if (nxt) {
|
||||
nxt = cpy_arg(&dport, nxt);
|
||||
if (dport) {
|
||||
port = atoi(dport);
|
||||
if (port > 0)
|
||||
port_be = short_be(port);
|
||||
}
|
||||
}
|
||||
|
||||
if (port == 0) {
|
||||
port_be = short_be(5555);
|
||||
}
|
||||
|
||||
printf("UDP NAT client started. Sending packets to %s:%d\n", daddr, short_be(port_be));
|
||||
|
||||
s = pico_socket_open(PICO_PROTO_IPV4, PICO_PROTO_UDP, &cb_udpnatclient);
|
||||
if (!s)
|
||||
exit(1);
|
||||
|
||||
pico_string_to_ipv4(daddr, &inaddr_dst.addr);
|
||||
|
||||
if (pico_socket_connect(s, &inaddr_dst, port_be) != 0)
|
||||
{
|
||||
printf("Error binding the port \n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
picoapp_dbg("New socket with port %u\n", s->local_port);
|
||||
|
||||
udpnatclient_inaddr_dst = inaddr_dst;
|
||||
udpnatclient_port_be = port_be;
|
||||
|
||||
if (!pico_timer_add(100, udpnatclient_send, s)) {
|
||||
printf("Failed to start send timer, exiting now\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!pico_timer_add(1000, udpnatclient_open_socket, 0)) {
|
||||
printf("Failed to start open_socket timer, exiting now\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
/*** END UDP NAT CLIENT ***/
|
||||
39
kernel/picotcp/test/examples/utils.h
Normal file
39
kernel/picotcp/test/examples/utils.h
Normal file
@ -0,0 +1,39 @@
|
||||
#ifndef PICO_EXAMPLES_UTILS_H
|
||||
#define PICO_EXAMPLES_UTILS_H
|
||||
#include <pico_stack.h>
|
||||
#define TCPSIZ (1024 * 1024 * 5)
|
||||
extern struct pico_ip4 ZERO_IP4;
|
||||
extern struct pico_ip_mreq ZERO_MREQ;
|
||||
extern struct pico_ip_mreq_source ZERO_MREQ_SRC;
|
||||
extern struct pico_ip6 ZERO_IP6;
|
||||
extern struct pico_ip_mreq ZERO_MREQ_IP6;
|
||||
extern struct pico_ip_mreq_source ZERO_MREQ_SRC_IP6;
|
||||
#define picoapp_dbg(...) do {} while(0)
|
||||
/* #define picoapp_dbg printf */
|
||||
extern int IPV6_MODE;
|
||||
|
||||
|
||||
extern struct pico_ip4 inaddr_any;
|
||||
extern struct pico_ip6 inaddr6_any;
|
||||
|
||||
extern char *cpy_arg(char **dst, char *str);
|
||||
|
||||
extern void deferred_exit(pico_time now, void *arg);
|
||||
|
||||
struct udpclient_pas {
|
||||
struct pico_socket *s;
|
||||
uint8_t loops;
|
||||
uint8_t subloops;
|
||||
uint16_t datasize;
|
||||
uint16_t sport;
|
||||
union pico_address dst;
|
||||
}; /* per application struct */
|
||||
|
||||
struct udpecho_pas {
|
||||
struct pico_socket *s;
|
||||
uint16_t sendto_port; /* big-endian */
|
||||
uint16_t datasize;
|
||||
}; /* per application struct */
|
||||
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user