mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2025-03-03 14:52:21 +02:00
Refactor address list lookup to include all returned addresses.
sckHostLookup() only returned the first address record returned from getaddrinfo(). The new AddressInfo object provides a full list of values returned from getaddrinfo(). Freeing the list is also handled by the object so there is no longer a need for FINALLY blocks to ensure the list is freed. Add the selected address to the client/server names for debugging purposes. This code does not attempt to connect to multiple addresses. It just lays the groundwork for a future commit to do so.
This commit is contained in:
parent
f42d927d2d
commit
edbd520c81
@ -133,6 +133,7 @@ SRCS = \
|
||||
common/io/limitRead.c \
|
||||
common/io/server.c \
|
||||
common/io/session.c \
|
||||
common/io/socket/address.c \
|
||||
common/io/socket/client.c \
|
||||
common/io/socket/common.c \
|
||||
common/io/socket/server.c \
|
||||
|
187
src/common/io/socket/address.c
Normal file
187
src/common/io/socket/address.c
Normal file
@ -0,0 +1,187 @@
|
||||
/***********************************************************************************************************************************
|
||||
Address Info
|
||||
***********************************************************************************************************************************/
|
||||
#include "build.auto.h"
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include "common/debug.h"
|
||||
#include "common/io/socket/address.h"
|
||||
#include "common/log.h"
|
||||
#include "common/memContext.h"
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Object type
|
||||
***********************************************************************************************************************************/
|
||||
struct AddressInfo
|
||||
{
|
||||
AddressInfoPub pub; // Publicly accessible variables
|
||||
};
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Free addrinfo linked list allocated by getaddrinfo()
|
||||
***********************************************************************************************************************************/
|
||||
static void
|
||||
addrInfoFreeResource(THIS_VOID)
|
||||
{
|
||||
THIS(AddressInfo);
|
||||
|
||||
FUNCTION_LOG_BEGIN(logLevelTrace);
|
||||
FUNCTION_LOG_PARAM(ADDRESS_INFO, this);
|
||||
FUNCTION_LOG_END();
|
||||
|
||||
ASSERT(this != NULL);
|
||||
|
||||
freeaddrinfo(*(struct addrinfo **)lstGet(this->pub.list, 0));
|
||||
|
||||
FUNCTION_LOG_RETURN_VOID();
|
||||
}
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
FN_EXTERN AddressInfo *
|
||||
addrInfoNew(const String *const host, unsigned int port)
|
||||
{
|
||||
FUNCTION_LOG_BEGIN(logLevelDebug);
|
||||
FUNCTION_LOG_PARAM(STRING, host);
|
||||
FUNCTION_LOG_PARAM(UINT, port);
|
||||
FUNCTION_LOG_END();
|
||||
|
||||
ASSERT(host != NULL);
|
||||
ASSERT(port != 0);
|
||||
|
||||
OBJ_NEW_BEGIN(AddressInfo, .childQty = MEM_CONTEXT_QTY_MAX, .callbackQty = 1)
|
||||
{
|
||||
*this = (AddressInfo)
|
||||
{
|
||||
.pub =
|
||||
{
|
||||
.host = strDup(host),
|
||||
.port = port,
|
||||
.list = lstNewP(sizeof(struct addrinfo *)),
|
||||
},
|
||||
};
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
{
|
||||
// Set hints that narrow the type of address we are looking for -- we'll take ipv4 or ipv6
|
||||
struct addrinfo hints = (struct addrinfo)
|
||||
{
|
||||
.ai_family = AF_UNSPEC,
|
||||
.ai_flags = AI_PASSIVE | AI_NUMERICSERV,
|
||||
.ai_socktype = SOCK_STREAM,
|
||||
.ai_protocol = IPPROTO_TCP,
|
||||
};
|
||||
|
||||
// Convert the port to a zero-terminated string for use with getaddrinfo()
|
||||
char portZ[CVT_BASE10_BUFFER_SIZE];
|
||||
cvtUIntToZ(port, portZ, sizeof(portZ));
|
||||
|
||||
// Do the lookup
|
||||
struct addrinfo *result;
|
||||
int error;
|
||||
|
||||
if ((error = getaddrinfo(strZ(host), portZ, &hints, &result)) != 0)
|
||||
THROW_FMT(HostConnectError, "unable to get address for '%s': [%d] %s", strZ(host), error, gai_strerror(error));
|
||||
|
||||
// Set free callback to ensure address info is freed
|
||||
memContextCallbackSet(objMemContext(this), addrInfoFreeResource, this);
|
||||
|
||||
// Convert address linked list to list
|
||||
lstAdd(this->pub.list, &result);
|
||||
|
||||
while (result->ai_next != NULL)
|
||||
{
|
||||
lstAdd(this->pub.list, &result->ai_next);
|
||||
result = result->ai_next;
|
||||
}
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
}
|
||||
OBJ_NEW_END();
|
||||
|
||||
FUNCTION_LOG_RETURN(ADDRESS_INFO, this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Convert address to a zero-terminated string
|
||||
***********************************************************************************************************************************/
|
||||
#define ADDR_INFO_STR_BUFFER_SIZE 48
|
||||
|
||||
static void
|
||||
addrInfoToZ(const struct addrinfo *const addrInfo, char *const address, const size_t addressSize)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM_P(VOID, addrInfo);
|
||||
FUNCTION_TEST_PARAM_P(CHAR, address);
|
||||
FUNCTION_TEST_PARAM(SIZE, addressSize);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
if (getnameinfo(addrInfo->ai_addr, addrInfo->ai_addrlen, address, (socklen_t)addressSize, 0, 0, NI_NUMERICHOST) != 0)
|
||||
{
|
||||
strncpy(address, "invalid", addressSize);
|
||||
address[addressSize - 1] = '\0';
|
||||
}
|
||||
|
||||
FUNCTION_TEST_RETURN_VOID();
|
||||
}
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
FN_EXTERN String *
|
||||
addrInfoToName(const String *const host, const unsigned int port, const struct addrinfo *const addrInfo)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRING, host);
|
||||
FUNCTION_TEST_PARAM(UINT, port);
|
||||
FUNCTION_TEST_PARAM_P(VOID, addrInfo);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
String *const result = strCatFmt(strNew(), "%s:%u", strZ(host), port);
|
||||
String *const address = addrInfoToStr(addrInfo);
|
||||
|
||||
if (!strEq(host, address))
|
||||
strCatFmt(result, " (%s)", strZ(address));
|
||||
|
||||
strFree(address);
|
||||
|
||||
FUNCTION_TEST_RETURN(STRING, result);
|
||||
}
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
FN_EXTERN String *
|
||||
addrInfoToStr(const struct addrinfo *const addrInfo)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM_P(VOID, addrInfo);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
char address[ADDR_INFO_STR_BUFFER_SIZE];
|
||||
addrInfoToZ(addrInfo, address, sizeof(address));
|
||||
|
||||
FUNCTION_TEST_RETURN(STRING, strNewZ(address));
|
||||
}
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
FN_EXTERN void
|
||||
addrInfoToLog(const AddressInfo *const this, StringStatic *const debugLog)
|
||||
{
|
||||
char address[48];
|
||||
|
||||
strStcFmt(debugLog, "{host: ");
|
||||
strToLog(addrInfoHost(this), debugLog);
|
||||
strStcFmt(debugLog, ", port: %u, list: [", addrInfoPort(this));
|
||||
|
||||
for (unsigned int listIdx = 0; listIdx < addrInfoSize(this); listIdx++)
|
||||
{
|
||||
const struct addrinfo *const addrInfo = addrInfoGet(this, listIdx);
|
||||
|
||||
if (listIdx != 0)
|
||||
strStcCat(debugLog, ", ");
|
||||
|
||||
addrInfoToZ(addrInfo, address, sizeof(address));
|
||||
strStcCat(debugLog, address);
|
||||
}
|
||||
|
||||
strStcCat(debugLog, "]}");
|
||||
}
|
91
src/common/io/socket/address.h
Normal file
91
src/common/io/socket/address.h
Normal file
@ -0,0 +1,91 @@
|
||||
/***********************************************************************************************************************************
|
||||
Address Info
|
||||
|
||||
Get address info for a host/address. If the input is a host then there may be multiple addresses that map to the host.
|
||||
***********************************************************************************************************************************/
|
||||
#ifndef COMMON_IO_SOCKET_ADDRESSINFO_H
|
||||
#define COMMON_IO_SOCKET_ADDRESSINFO_H
|
||||
|
||||
#include <netdb.h>
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Object type
|
||||
***********************************************************************************************************************************/
|
||||
typedef struct AddressInfo AddressInfo;
|
||||
|
||||
#include "common/type/list.h"
|
||||
#include "common/type/object.h"
|
||||
#include "common/type/string.h"
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Constructor
|
||||
***********************************************************************************************************************************/
|
||||
FN_EXTERN AddressInfo *addrInfoNew(const String *const host, unsigned int port);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Getters/Setters
|
||||
***********************************************************************************************************************************/
|
||||
typedef struct AddressInfoPub
|
||||
{
|
||||
const String *host; // Host for address info lookup
|
||||
unsigned int port; // Port for address info lookup
|
||||
List *list; // List of addresses for the host
|
||||
} AddressInfoPub;
|
||||
|
||||
// Get address
|
||||
FN_INLINE_ALWAYS const struct addrinfo *
|
||||
addrInfoGet(const AddressInfo *const this, const unsigned int index)
|
||||
{
|
||||
return *(const struct addrinfo **)lstGet(THIS_PUB(AddressInfo)->list, index);
|
||||
}
|
||||
|
||||
// Get lookup host
|
||||
FN_INLINE_ALWAYS const String *
|
||||
addrInfoHost(const AddressInfo *const this)
|
||||
{
|
||||
return THIS_PUB(AddressInfo)->host;
|
||||
}
|
||||
|
||||
// Get lookup port
|
||||
FN_INLINE_ALWAYS unsigned int
|
||||
addrInfoPort(const AddressInfo *const this)
|
||||
{
|
||||
return THIS_PUB(AddressInfo)->port;
|
||||
}
|
||||
|
||||
// Size of address list
|
||||
FN_INLINE_ALWAYS unsigned int
|
||||
addrInfoSize(const AddressInfo *const this)
|
||||
{
|
||||
return lstSize(THIS_PUB(AddressInfo)->list);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Destructor
|
||||
***********************************************************************************************************************************/
|
||||
FN_INLINE_ALWAYS void
|
||||
addrInfoFree(AddressInfo *const this)
|
||||
{
|
||||
objFree(this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Helper functions
|
||||
***********************************************************************************************************************************/
|
||||
// Convert address info to string
|
||||
FN_EXTERN String *addrInfoToStr(const struct addrinfo *addrInfo);
|
||||
|
||||
// Generate name for the host/port/address combination (address is omitted if it equals host)
|
||||
FN_EXTERN String *addrInfoToName(const String *host, unsigned int port, const struct addrinfo *addrInfo);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Macros for function logging
|
||||
***********************************************************************************************************************************/
|
||||
FN_EXTERN void addrInfoToLog(const AddressInfo *this, StringStatic *debugLog);
|
||||
|
||||
#define FUNCTION_LOG_ADDRESS_INFO_TYPE \
|
||||
AddressInfo *
|
||||
#define FUNCTION_LOG_ADDRESS_INFO_FORMAT(value, buffer, bufferSize) \
|
||||
FUNCTION_LOG_OBJECT_FORMAT(value, addrInfoToLog, buffer, bufferSize)
|
||||
|
||||
#endif
|
@ -10,6 +10,7 @@ Socket Client
|
||||
|
||||
#include "common/debug.h"
|
||||
#include "common/io/client.h"
|
||||
#include "common/io/socket/address.h"
|
||||
#include "common/io/socket/client.h"
|
||||
#include "common/io/socket/common.h"
|
||||
#include "common/io/socket/session.h"
|
||||
@ -83,22 +84,14 @@ sckClientOpen(THIS_VOID)
|
||||
TRY_BEGIN()
|
||||
{
|
||||
// Get an address for the host. We are only going to try the first address returned.
|
||||
struct addrinfo *addressFound = sckHostLookup(this->host, this->port);
|
||||
const struct addrinfo *const addressFound = addrInfoGet(addrInfoNew(this->host, this->port), 0);
|
||||
|
||||
// Connect to the host
|
||||
TRY_BEGIN()
|
||||
{
|
||||
fd = socket(addressFound->ai_family, addressFound->ai_socktype, addressFound->ai_protocol);
|
||||
THROW_ON_SYS_ERROR(fd == -1, HostConnectError, "unable to create socket");
|
||||
fd = socket(addressFound->ai_family, addressFound->ai_socktype, addressFound->ai_protocol);
|
||||
THROW_ON_SYS_ERROR(fd == -1, HostConnectError, "unable to create socket");
|
||||
|
||||
sckOptionSet(fd);
|
||||
sckConnect(fd, this->host, this->port, addressFound, waitRemaining(wait));
|
||||
}
|
||||
FINALLY()
|
||||
{
|
||||
freeaddrinfo(addressFound);
|
||||
}
|
||||
TRY_END();
|
||||
sckOptionSet(fd);
|
||||
sckConnect(fd, this->host, this->port, addressFound, waitRemaining(wait));
|
||||
|
||||
// Create the session
|
||||
MEM_CONTEXT_PRIOR_BEGIN()
|
||||
@ -106,6 +99,10 @@ sckClientOpen(THIS_VOID)
|
||||
result = sckSessionNew(ioSessionRoleClient, fd, this->host, this->port, this->timeoutSession);
|
||||
}
|
||||
MEM_CONTEXT_PRIOR_END();
|
||||
|
||||
// Update client name to include address
|
||||
strTrunc(this->name);
|
||||
strCat(this->name, addrInfoToName(this->host, this->port, addressFound));
|
||||
}
|
||||
CATCH_ANY()
|
||||
{
|
||||
@ -176,7 +173,7 @@ sckClientNew(const String *const host, const unsigned int port, const TimeMSec t
|
||||
{
|
||||
.host = strDup(host),
|
||||
.port = port,
|
||||
.name = strNewFmt("%s:%u", strZ(host), port),
|
||||
.name = strCatFmt(strNew(), "%s:%u", strZ(host), port),
|
||||
.timeoutConnect = timeoutConnect,
|
||||
.timeoutSession = timeoutSession,
|
||||
};
|
||||
|
@ -10,6 +10,7 @@ Socket Common Functions
|
||||
|
||||
#include "common/debug.h"
|
||||
#include "common/io/fd.h"
|
||||
#include "common/io/socket/address.h"
|
||||
#include "common/io/socket/common.h"
|
||||
#include "common/log.h"
|
||||
#include "common/wait.h"
|
||||
@ -55,41 +56,6 @@ sckInit(bool block, bool keepAlive, int tcpKeepAliveCount, int tcpKeepAliveIdle,
|
||||
FUNCTION_LOG_RETURN_VOID();
|
||||
}
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
FN_EXTERN struct addrinfo *
|
||||
sckHostLookup(const String *const host, unsigned int port)
|
||||
{
|
||||
FUNCTION_LOG_BEGIN(logLevelDebug);
|
||||
FUNCTION_LOG_PARAM(STRING, host);
|
||||
FUNCTION_LOG_PARAM(UINT, port);
|
||||
FUNCTION_LOG_END();
|
||||
|
||||
ASSERT(host != NULL);
|
||||
ASSERT(port != 0);
|
||||
|
||||
// Set hints that narrow the type of address we are looking for -- we'll take ipv4 or ipv6
|
||||
struct addrinfo hints = (struct addrinfo)
|
||||
{
|
||||
.ai_family = AF_UNSPEC,
|
||||
.ai_flags = AI_PASSIVE,
|
||||
.ai_socktype = SOCK_STREAM,
|
||||
.ai_protocol = IPPROTO_TCP,
|
||||
};
|
||||
|
||||
// Convert the port to a zero-terminated string for use with getaddrinfo()
|
||||
char portZ[CVT_BASE10_BUFFER_SIZE];
|
||||
cvtUIntToZ(port, portZ, sizeof(portZ));
|
||||
|
||||
// Do the lookup
|
||||
struct addrinfo *result;
|
||||
int error;
|
||||
|
||||
if ((error = getaddrinfo(strZ(host), portZ, &hints, &result)) != 0)
|
||||
THROW_FMT(HostConnectError, "unable to get address for '%s': [%d] %s", strZ(host), error, gai_strerror(error));
|
||||
|
||||
FUNCTION_LOG_RETURN_P(VOID, result);
|
||||
}
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
FN_EXTERN void
|
||||
sckOptionSet(int fd)
|
||||
@ -204,7 +170,7 @@ sckConnect(int fd, const String *host, unsigned int port, const struct addrinfo
|
||||
{
|
||||
// Wait for write-ready
|
||||
if (!fdReadyWrite(fd, timeout))
|
||||
THROW_FMT(HostConnectError, "timeout connecting to '%s:%u'", strZ(host), port);
|
||||
THROW_FMT(HostConnectError, "timeout connecting to '%s'", strZ(addrInfoToName(host, port, hostAddress)));
|
||||
|
||||
// Check for success or error. If the connection was successful this will set errNo to 0.
|
||||
socklen_t errNoLen = sizeof(errNo);
|
||||
@ -215,7 +181,10 @@ sckConnect(int fd, const String *host, unsigned int port, const struct addrinfo
|
||||
|
||||
// Throw error if it is still set
|
||||
if (errNo != 0)
|
||||
THROW_SYS_ERROR_CODE_FMT(errNo, HostConnectError, "unable to connect to '%s:%u'", strZ(host), port);
|
||||
{
|
||||
THROW_SYS_ERROR_CODE_FMT(
|
||||
errNo, HostConnectError, "unable to connect to '%s'", strZ(addrInfoToName(host, port, hostAddress)));
|
||||
}
|
||||
}
|
||||
|
||||
FUNCTION_LOG_RETURN_VOID();
|
||||
|
@ -15,9 +15,6 @@ Functions
|
||||
// Initialize settings for socket connections (some are used only for TCP)
|
||||
FN_EXTERN void sckInit(bool block, bool keepAlive, int tcpKeepAliveCount, int tcpKeepAliveIdle, int tcpKeepAliveInterval);
|
||||
|
||||
// Get address info for a host/address. The caller is responsible for freeing addrinfo.
|
||||
FN_EXTERN struct addrinfo *sckHostLookup(const String *const host, unsigned int port);
|
||||
|
||||
// Set options on a socket
|
||||
FN_EXTERN void sckOptionSet(int fd);
|
||||
|
||||
|
@ -10,6 +10,7 @@ Socket Server
|
||||
|
||||
#include "common/debug.h"
|
||||
#include "common/io/server.h"
|
||||
#include "common/io/socket/address.h"
|
||||
#include "common/io/socket/common.h"
|
||||
#include "common/io/socket/server.h"
|
||||
#include "common/io/socket/session.h"
|
||||
@ -159,39 +160,35 @@ sckServerNew(const String *const address, const unsigned int port, const TimeMSe
|
||||
{
|
||||
.address = strDup(address),
|
||||
.port = port,
|
||||
.name = strNewFmt("%s:%u", strZ(address), port),
|
||||
.name = strCatFmt(strNew(), "%s:%u", strZ(address), port),
|
||||
.timeout = timeout,
|
||||
};
|
||||
|
||||
// Lookup address
|
||||
struct addrinfo *const addressFound = sckHostLookup(this->address, this->port);
|
||||
const struct addrinfo *const addressFound = addrInfoGet(addrInfoNew(this->address, this->port), 0);
|
||||
|
||||
TRY_BEGIN()
|
||||
{
|
||||
// Create socket
|
||||
THROW_ON_SYS_ERROR(
|
||||
(this->socket = socket(addressFound->ai_family, SOCK_STREAM, 0)) == -1, FileOpenError, "unable to create socket");
|
||||
// Create socket
|
||||
THROW_ON_SYS_ERROR(
|
||||
(this->socket = socket(addressFound->ai_family, SOCK_STREAM, 0)) == -1, FileOpenError, "unable to create socket");
|
||||
|
||||
// Set the address as reusable so we can bind again quickly after a restart or crash
|
||||
int reuseAddr = 1;
|
||||
// Set the address as reusable so we can bind again quickly after a restart or crash
|
||||
int reuseAddr = 1;
|
||||
|
||||
THROW_ON_SYS_ERROR(
|
||||
setsockopt(this->socket, SOL_SOCKET, SO_REUSEADDR, &reuseAddr, sizeof(reuseAddr)) == -1, ProtocolError,
|
||||
"unable to set SO_REUSEADDR");
|
||||
THROW_ON_SYS_ERROR(
|
||||
setsockopt(this->socket, SOL_SOCKET, SO_REUSEADDR, &reuseAddr, sizeof(reuseAddr)) == -1, ProtocolError,
|
||||
"unable to set SO_REUSEADDR");
|
||||
|
||||
// Ensure file descriptor is closed
|
||||
memContextCallbackSet(objMemContext(this), sckServerFreeResource, this);
|
||||
// Ensure file descriptor is closed
|
||||
memContextCallbackSet(objMemContext(this), sckServerFreeResource, this);
|
||||
|
||||
// Bind the address
|
||||
THROW_ON_SYS_ERROR(
|
||||
bind(this->socket, addressFound->ai_addr, addressFound->ai_addrlen) == -1, FileOpenError,
|
||||
"unable to bind socket");
|
||||
}
|
||||
FINALLY()
|
||||
{
|
||||
freeaddrinfo(addressFound);
|
||||
}
|
||||
TRY_END();
|
||||
// Update server name to include address
|
||||
strTrunc(this->name);
|
||||
strCat(this->name, addrInfoToName(this->address, this->port, addressFound));
|
||||
|
||||
// Bind the address
|
||||
THROW_ON_SYS_ERROR(
|
||||
bind(this->socket, addressFound->ai_addr, addressFound->ai_addrlen) == -1, FileOpenError,
|
||||
"unable to bind socket");
|
||||
|
||||
// Listen for client connections. It might be a good idea to make the backlog configurable but this value seems OK for now.
|
||||
THROW_ON_SYS_ERROR(listen(this->socket, 100) == -1, FileOpenError, "unable to listen on socket");
|
||||
|
@ -199,6 +199,7 @@ src_pgbackrest = [
|
||||
'common/io/limitRead.c',
|
||||
'common/io/server.c',
|
||||
'common/io/session.c',
|
||||
'common/io/socket/address.c',
|
||||
'common/io/socket/client.c',
|
||||
'common/io/socket/common.c',
|
||||
'common/io/socket/server.c',
|
||||
|
@ -362,7 +362,7 @@ unit:
|
||||
|
||||
# ----------------------------------------------------------------------------------------------------------------------------
|
||||
- name: io-tls
|
||||
total: 5
|
||||
total: 6
|
||||
feature: SOCKET
|
||||
harness: server
|
||||
harness:
|
||||
@ -380,6 +380,7 @@ unit:
|
||||
- common/io/tls/common
|
||||
- common/io/tls/server
|
||||
- common/io/tls/session
|
||||
- common/io/socket/address
|
||||
- common/io/socket/client
|
||||
- common/io/socket/common
|
||||
- common/io/socket/server
|
||||
|
@ -306,7 +306,7 @@ testRun(void)
|
||||
|
||||
TEST_ERROR_FMT(
|
||||
httpRequestResponse(httpRequestNewP(client, STRDEF("GET"), STRDEF("/")), false), HostConnectError,
|
||||
"unable to connect to 'localhost:%u': [111] Connection refused",
|
||||
"unable to connect to 'localhost:%u (127.0.0.1)': [111] Connection refused",
|
||||
hrnServerPort(0));
|
||||
|
||||
HRN_FORK_BEGIN()
|
||||
|
@ -151,6 +151,60 @@ testRun(void)
|
||||
THROW_ON_SYS_ERROR_FMT(
|
||||
chmod(HRN_SERVER_CLIENT_KEY, 0600) == -1, FileModeError, "unable to set mode on " HRN_SERVER_CLIENT_KEY);
|
||||
|
||||
// *****************************************************************************************************************************
|
||||
if (testBegin("AddressInfo"))
|
||||
{
|
||||
#ifdef TEST_CONTAINER_REQUIRED
|
||||
HRN_SYSTEM("echo \"127.0.0.1 test-addr-loop.pgbackrest.org\" | sudo tee -a /etc/hosts > /dev/null");
|
||||
HRN_SYSTEM("echo \"::1 test-addr-loop.pgbackrest.org\" | sudo tee -a /etc/hosts > /dev/null");
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
TEST_TITLE("lookup address info");
|
||||
|
||||
AddressInfo *addrInfo = NULL;
|
||||
TEST_ASSIGN(addrInfo, addrInfoNew(STRDEF("test-addr-loop.pgbackrest.org"), 443), "addr list");
|
||||
TEST_RESULT_STR_Z(addrInfoHost(addrInfo), "test-addr-loop.pgbackrest.org", "check host");
|
||||
TEST_RESULT_UINT(addrInfoPort(addrInfo), 443, "check port");
|
||||
TEST_RESULT_UINT(addrInfoSize(addrInfo), 2, "check size");
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
TEST_TITLE("addrInfoToLog");
|
||||
|
||||
char logBuf[STACK_TRACE_PARAM_MAX];
|
||||
|
||||
TEST_RESULT_VOID(FUNCTION_LOG_OBJECT_FORMAT(addrInfo, addrInfoToLog, logBuf, sizeof(logBuf)), "addrInfoToLog");
|
||||
TEST_RESULT_Z(
|
||||
logBuf,
|
||||
zNewFmt(
|
||||
"{host: {\"test-addr-loop.pgbackrest.org\"}, port: 443, list: [%s, %s]}",
|
||||
strZ(addrInfoToStr(addrInfoGet(addrInfo, 0))), strZ(addrInfoToStr(addrInfoGet(addrInfo, 1)))),
|
||||
"check log");
|
||||
|
||||
// Munge address so it is invalid
|
||||
(*(struct addrinfo **)lstGet(addrInfo->pub.list, 0))->ai_addr = NULL;
|
||||
|
||||
TEST_RESULT_VOID(FUNCTION_LOG_OBJECT_FORMAT(addrInfo, addrInfoToLog, logBuf, sizeof(logBuf)), "addrInfoToLog");
|
||||
TEST_RESULT_Z(
|
||||
logBuf,
|
||||
zNewFmt(
|
||||
"{host: {\"test-addr-loop.pgbackrest.org\"}, port: 443, list: [invalid, %s]}",
|
||||
strZ(addrInfoToStr(addrInfoGet(addrInfo, 1)))),
|
||||
"check log");
|
||||
TEST_RESULT_STR_Z(addrInfoToStr(addrInfoGet(addrInfo, 0)), "invalid", "check invalid");
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
TEST_TITLE("free");
|
||||
|
||||
TEST_RESULT_VOID(addrInfoFree(addrInfo), "free");
|
||||
#endif
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
TEST_TITLE("addrInfoToStr (invalid)");
|
||||
|
||||
struct addrinfo addrInfoInvalid = {0};
|
||||
|
||||
TEST_RESULT_STR_Z(addrInfoToStr(&addrInfoInvalid), "invalid", "check invalid");
|
||||
}
|
||||
|
||||
// *****************************************************************************************************************************
|
||||
if (testBegin("Socket Common"))
|
||||
{
|
||||
@ -314,7 +368,7 @@ testRun(void)
|
||||
|
||||
TEST_ASSIGN(client, sckClientNew(STRDEF("localhost"), hrnServerPort(0), 100, 100), "new client");
|
||||
TEST_ERROR_FMT(
|
||||
ioClientOpen(client), HostConnectError, "unable to connect to 'localhost:%u': [111] Connection refused",
|
||||
ioClientOpen(client), HostConnectError, "unable to connect to 'localhost:%u (127.0.0.1)': [111] Connection refused",
|
||||
hrnServerPort(0));
|
||||
|
||||
// This address should not be in use in a test environment -- if it is the test will fail
|
||||
@ -397,7 +451,7 @@ testRun(void)
|
||||
client, tlsClientNewP(sckClientNew(STRDEF("localhost"), hrnServerPort(0), 100, 100), STRDEF("X"), 100, 100, true),
|
||||
"new client");
|
||||
TEST_ERROR_FMT(
|
||||
ioClientOpen(client), HostConnectError, "unable to connect to 'localhost:%u': [111] Connection refused",
|
||||
ioClientOpen(client), HostConnectError, "unable to connect to 'localhost:%u (127.0.0.1)': [111] Connection refused",
|
||||
hrnServerPort(0));
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
@ -577,7 +631,8 @@ testRun(void)
|
||||
sckClientNew(STRDEF("localhost"), hrnServerPort(0), 5000, 5000), STRDEF("X"), 0, 0, true,
|
||||
.caPath = STRDEF("/bogus"))),
|
||||
CryptoError,
|
||||
"unable to verify certificate presented by 'localhost:%u': [20] unable to get local issuer certificate",
|
||||
"unable to verify certificate presented by 'localhost:%u (127.0.0.1)': [20] unable to get local issuer"
|
||||
" certificate",
|
||||
hrnServerPort(0));
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------
|
||||
@ -632,7 +687,8 @@ testRun(void)
|
||||
sckClientNew(STRDEF("localhost"), hrnServerPort(0), 5000, 5000), STRDEF("X"), 0, 0, true,
|
||||
.caFile = STRDEF(HRN_SERVER_CERT))),
|
||||
CryptoError,
|
||||
"unable to verify certificate presented by 'localhost:%u': [20] unable to get local issuer certificate",
|
||||
"unable to verify certificate presented by 'localhost:%u (127.0.0.1)': [20] unable to get local issuer"
|
||||
" certificate",
|
||||
hrnServerPort(0));
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------
|
||||
@ -680,7 +736,8 @@ testRun(void)
|
||||
STRDEF(TEST_PATH "/server-cn-only.crt"), 5000);
|
||||
IoSession *socketSession = NULL;
|
||||
|
||||
TEST_RESULT_STR(ioServerName(socketServer), strNewFmt("localhost:%u", hrnServerPort(0)), "socket server name");
|
||||
TEST_RESULT_STR(
|
||||
ioServerName(socketServer), strNewFmt("localhost:%u (127.0.0.1)", hrnServerPort(0)), "socket server name");
|
||||
TEST_RESULT_STR_Z(ioServerName(tlsServer), "localhost", "tls server name");
|
||||
|
||||
// Invalid client cert
|
||||
|
Loading…
x
Reference in New Issue
Block a user