socket examples: add tests for server and client applications

This commit is contained in:
David Cermak
2020-03-17 20:30:33 +01:00
committed by bot
parent 63aa0d6e9c
commit 995ef85e85
33 changed files with 696 additions and 328 deletions
@@ -0,0 +1,3 @@
idf_component_register(SRCS "addr_from_stdin.c"
INCLUDE_DIRS "include"
PRIV_REQUIRES protocol_examples_common)
@@ -0,0 +1,6 @@
# Socket address input
This directory contains a common component for socket client examples which read IP address from stdin (if configured).
This option is typically used in the CI, but could be enabled in the project configuration.
In that case this component is used to receive a string that is evaluated and processed to output
socket structures to open a connection.
@@ -0,0 +1,65 @@
#include <string.h>
#include "esp_system.h"
#include "esp_log.h"
#include "esp_netif.h"
#include "protocol_examples_common.h"
#include "lwip/sockets.h"
#include <lwip/netdb.h>
#include <arpa/inet.h>
#define HOST_IP_SIZE 128
esp_err_t get_addr_from_stdin(int port, int sock_type, int *ip_protocol, int *addr_family, struct sockaddr_in6 *dest_addr)
{
char host_ip[HOST_IP_SIZE];
int len;
static bool already_init = false;
// this function could be called multiple times -> make sure UART init runs only once
if (!already_init) {
example_configure_stdin_stdout();
already_init = true;
}
// ignore empty or LF only string (could receive from DUT class)
do {
fgets(host_ip, HOST_IP_SIZE, stdin);
len = strlen(host_ip);
} while (len<=1 && host_ip[0] == '\n');
host_ip[len - 1] = '\0';
struct addrinfo hints, *addr_list, *cur;
memset( &hints, 0, sizeof( hints ) );
// run getaddrinfo() to decide on the IP protocol
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = sock_type;
hints.ai_protocol = IPPROTO_TCP;
if( getaddrinfo( host_ip, NULL, &hints, &addr_list ) != 0 ) {
return ESP_FAIL;
}
for( cur = addr_list; cur != NULL; cur = cur->ai_next ) {
memcpy(dest_addr, cur->ai_addr, sizeof(*dest_addr));
if (cur->ai_family == AF_INET) {
*ip_protocol = IPPROTO_IP;
*addr_family = AF_INET;
// add port number and return on first IPv4 match
((struct sockaddr_in*)dest_addr)->sin_port = htons(port);
freeaddrinfo( addr_list );
return ESP_OK;
} else if (cur->ai_family == AF_INET6) {
*ip_protocol = IPPROTO_IPV6;
*addr_family = AF_INET6;
// add port and interface number and return on first IPv6 match
dest_addr->sin6_port = htons(port);
dest_addr->sin6_scope_id = esp_netif_get_netif_impl_index(EXAMPLE_INTERFACE);
freeaddrinfo( addr_list );
return ESP_OK;
}
}
// no match found
freeaddrinfo( addr_list );
return ESP_FAIL;
}
@@ -0,0 +1,5 @@
#
# Component Makefile
#
COMPONENT_ADD_INCLUDEDIRS := include
COMPONENT_SRCDIRS := .
@@ -0,0 +1,22 @@
#include "lwip/sys.h"
#include <lwip/netdb.h>
#include <arpa/inet.h>
/**
* @brief Read and evaluate IP address from stdin
*
* This API reads stdin and parses the input address using getaddrinfo()
* to fill in struct sockaddr_in6 (for both IPv4 and IPv6) used to open
* a socket. IP protocol is guessed from the IP address string.
*
* @param[in] port port number of expected connection
* @param[in] sock_type expected protocol: SOCK_STREAM or SOCK_DGRAM
* @param[out] ip_protocol resultant IP protocol: IPPROTO_IP or IPPROTO_IP6
* @param[out] addr_family resultant address family: AF_INET or AF_INET6
* @param[out] dest_addr sockaddr_in6 structure (for both IPv4 and IPv6)
* @return ESP_OK on success, ESP_FAIL otherwise
*/
esp_err_t get_addr_from_stdin(int port, int sock_type,
int *ip_protocol,
int *addr_family,
struct sockaddr_in6 *dest_addr);