Skip to content

Commit

Permalink
fix(sockutls): Cleanup the tests
Browse files Browse the repository at this point in the history
  • Loading branch information
david-cermak committed Oct 14, 2024
1 parent ea6630d commit 5a7b45d
Show file tree
Hide file tree
Showing 12 changed files with 417 additions and 190 deletions.
2 changes: 2 additions & 0 deletions components/sock_utils/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
idf_component_register(SRCS "src/getnameinfo.c"
"src/ifaddrs.c"
"src/gai_strerror.c"
"src/socketpair.c"
INCLUDE_DIRS "include"
PRIV_REQUIRES lwip esp_netif)
31 changes: 31 additions & 0 deletions components/sock_utils/include/gai_strerror.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once

#include "lwip/sockets.h"
#include "netdb_macros.h"

#ifdef __cplusplus
extern "C" {
#endif

#ifdef CONFIG_IDF_TARGET_LINUX
// namespace with esp_ on linux to avoid duplication of symbols
#define gai_strerror esp_gai_strerror
#endif

/**
* @brief Returns a string describing a `getaddrinfo()` error code.
*
* @param[in] ecode Error code returned by `getaddrinfo()`.
*
* @return A pointer to a string describing the error.
*/
const char *gai_strerror(int ecode);

#ifdef __cplusplus
}
#endif
40 changes: 40 additions & 0 deletions components/sock_utils/include/getnameinfo.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once

#include "lwip/sockets.h"

#ifdef CONFIG_IDF_TARGET_LINUX
// namespace with esp_ on linux to avoid conflict of symbols
#define getnameinfo esp_getnameinfo
#endif

#ifdef __cplusplus
extern "C" {
#endif

/**
* @brief Converts a socket address to a corresponding host and service name.
*
* @param[in] addr Pointer to the socket address structure.
* @param[in] addrlen Length of the socket address.
* @param[out] host Buffer to store the host name.
* @param[in] hostlen Length of the host buffer.
* @param[out] serv Buffer to store the service name.
* @param[in] servlen Length of the service buffer.
* @param[in] flags Flags to modify the behavior of the function.
*
* @return
* - 0 on success.
* - Non-zero on failure, with `errno` set to indicate the error.
*/
int getnameinfo(const struct sockaddr *addr, socklen_t addrlen,
char *host, socklen_t hostlen,
char *serv, socklen_t servlen, int flags);

#ifdef __cplusplus
}
#endif
67 changes: 29 additions & 38 deletions components/sock_utils/include/ifaddrs.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,60 +6,51 @@
#pragma once

#include "lwip/sockets.h"

#ifndef NI_NUMERICHOST
#define NI_NUMERICHOST 0x1
#endif

#ifndef IFF_UP
#define IFF_UP 0x1
#endif

#ifndef IFF_LOOPBACK
#define IFF_LOOPBACK 0x8
#endif

#ifndef NI_NUMERICSERV
#define NI_NUMERICSERV 0x8
#endif

#ifndef NI_DGRAM
#define NI_DGRAM 0x00000010
#endif

#ifndef EAI_BADFLAGS
#define EAI_BADFLAGS 3
#endif

#ifndef AF_UNIX
#define AF_UNIX 1
#endif
#include "netdb_macros.h"
// include also other related headers to simplify porting of linux libs
#include "getnameinfo.h"
#include "socketpair.h"
#include "gai_strerror.h"

#ifdef __cplusplus
extern "C" {
#endif

#ifdef CONFIG_IDF_TARGET_LINUX
// namespace with esp_ on linux to avoid duplication of symbols
#define getifaddrs esp_getifaddrs
#define freeifaddrs esp_freeifaddrs
#endif

/**
* @brief Simplified version of ifaddr struct
*/
struct ifaddrs {
struct ifaddrs *ifa_next; /* Next item in list */
char *ifa_name; /* Name of interface */
struct sockaddr *ifa_addr; /* Address of interface */
int ifa_flags;
};

/**
* @brief Retrieves a list of network interfaces and their addresses.
*
* @param[out] ifap Pointer to a linked list of `struct ifaddrs`. On success, `*ifap` will be set
* to the head of the list.
*
* @return
* - 0 on success.
* - -1 on failure, with `errno` set to indicate the error.
*/
int getifaddrs(struct ifaddrs **ifap);

/**
* @brief Frees the memory allocated by `getifaddrs()`.
*
* @param[in] ifa Pointer to the linked list of network interfaces to be freed.
*/
void freeifaddrs(struct ifaddrs *ifa);

#ifdef CONFIG_IDF_TARGET_LINUX
#define getnameinfo lwip_getnameinfo
#endif

int getnameinfo(const struct sockaddr *addr, socklen_t addrlen,
char *host, socklen_t hostlen,
char *serv, socklen_t servlen, int flags);

int socketpair(int domain, int type, int protocol, int sv[2]);

#ifdef __cplusplus
}
#endif
34 changes: 34 additions & 0 deletions components/sock_utils/include/netdb_macros.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once

#ifndef NI_NUMERICHOST
#define NI_NUMERICHOST 0x1
#endif

#ifndef IFF_UP
#define IFF_UP 0x1
#endif

#ifndef IFF_LOOPBACK
#define IFF_LOOPBACK 0x8
#endif

#ifndef NI_NUMERICSERV
#define NI_NUMERICSERV 0x8
#endif

#ifndef NI_DGRAM
#define NI_DGRAM 0x00000010
#endif

#ifndef EAI_BADFLAGS
#define EAI_BADFLAGS 3
#endif

#ifndef AF_UNIX
#define AF_UNIX 1
#endif
49 changes: 49 additions & 0 deletions components/sock_utils/include/socketpair.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once

#include "lwip/sockets.h"
#include "netdb_macros.h"

#ifdef __cplusplus
extern "C" {
#endif

#ifdef CONFIG_IDF_TARGET_LINUX
// namespace with esp_ on linux to avoid conflict of symbols
#define socketpair esp_socketpair
#define pipe esp_pipe
#endif

/**
* @brief Creates a pair of connected sockets.
*
* @param[in] domain Communication domain (e.g., AF_UNIX).
* @param[in] type Socket type (e.g., SOCK_STREAM).
* @param[in] protocol Protocol to be used (usually 0).
* @param[out] sv Array of two integers to store the file descriptors of the created sockets.
*
* @return
* - 0 on success.
* - -1 on failure, with `errno` set to indicate the error.
*/
int socketpair(int domain, int type, int protocol, int sv[2]);

/**
* @brief Creates a unidirectional data channel (pipe).
*
* @param[out] pipefd Array of two integers where the file descriptors for the read and write ends
* of the pipe will be stored.
*
* @return
* - 0 on success.
* - -1 on failure, with `errno` set to indicate the error.
*/
int pipe(int pipefd[2]);

#ifdef __cplusplus
}
#endif
16 changes: 16 additions & 0 deletions components/sock_utils/src/gai_strerror.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include "gai_strerror.h"

const char *gai_strerror(int ecode)
{
static char str[32];
if (snprintf(str, sizeof(str), "EAI error:%d", ecode) < 0) {
return "gai_strerror() failed";
}
return str;
}
79 changes: 0 additions & 79 deletions components/sock_utils/src/getnameinfo.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,82 +46,3 @@ int getnameinfo(const struct sockaddr *addr, socklen_t addrlen,

return 0;
}

#define INVALID_SOCKET (-1)

static const char *TAG = "socket_helpers";

static int set_nonblocking(int sock)
{
int opt;
opt = fcntl(sock, F_GETFL, 0);
if (opt == -1) {
return -1;
}
if (fcntl(sock, F_SETFL, opt | O_NONBLOCK) == -1) {
return -1;
}
return 0;
}

int socketpair(int domain, int type, int protocol, int sv[2])
{
struct sockaddr_storage ss;
struct sockaddr_in *sa = (struct sockaddr_in *)&ss;
socklen_t ss_len = sizeof(struct sockaddr_in);
int fd1 = INVALID_SOCKET;
int fd2 = INVALID_SOCKET;
int listenfd = INVALID_SOCKET;
int ret = 0; // Success

sa->sin_family = AF_INET;
sa->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
sa->sin_port = 0;
listenfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
ESP_GOTO_ON_FALSE(listenfd != INVALID_SOCKET, -1, err, TAG, "Cannot create listening socket");
ESP_GOTO_ON_FALSE(listen(listenfd, 1) == 0, -1, err, TAG, "Failed to listen");

memset(&ss, 0, sizeof(ss));
ss_len = sizeof(ss);
ESP_GOTO_ON_FALSE(getsockname(listenfd, (struct sockaddr *)&ss, &ss_len) >= 0, -1, err, TAG, "getsockname failed");

sa->sin_family = AF_INET;
sa->sin_addr.s_addr = htonl(INADDR_LOOPBACK);

fd1 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
ESP_GOTO_ON_FALSE(fd1 != INVALID_SOCKET, -1, err, TAG, "Cannot create read side socket");
ESP_GOTO_ON_FALSE(set_nonblocking(fd1) == 0, -1, err, TAG, "Failed to set socket to nonblocking mode");
if (connect(fd1, (struct sockaddr *)&ss, ss_len) < 0) {
ESP_GOTO_ON_FALSE(errno == EINPROGRESS || errno == EWOULDBLOCK, -1, err, TAG, "Failed to connect fd1");
}
fd2 = accept(listenfd, NULL, 0);
if (fd2 == -1) {
ESP_GOTO_ON_FALSE(errno == EINPROGRESS || errno == EWOULDBLOCK, -1, err, TAG, "Failed to accept fd2");
}
ESP_GOTO_ON_FALSE(set_nonblocking(fd2) == 0, -1, err, TAG, "Failed to set socket to nonblocking mode");

close(listenfd);
sv[0] = fd1;
sv[1] = fd2;
return ret;

err:
if (listenfd != INVALID_SOCKET) {
close(listenfd);
}
if (fd1 != INVALID_SOCKET) {
close(fd1);
}
if (fd2 != INVALID_SOCKET) {
close(fd2);
}
return ret;
}

int pipe(int pipefd[2])
{
if (socketpair(AF_UNIX, SOCK_STREAM, 0, pipefd) == -1) {
return -1;
}
return 0;
}
Loading

0 comments on commit 5a7b45d

Please sign in to comment.