mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2025-03-29 21:47:21 +02:00
Add IoClient and IoSession interfaces.
These interfaces allow the HttpClient and HttpSession objects to work with protocols other than TLS, .e.g. plain sockets. This is necessary to allow standard HTTP -- right now only HTTPS is allowed, i.e. HTTP over TLS. For now only TlsClient and TlsSession have been converted to the new interfaces. SocketClient and SocketSession will also need to be converted but first sckSessionReadyRead() and sckSessionReadyWrite() need to be moved into the IoRead and IoWrite interfaces, since they are not a good fit for IoSession.
This commit is contained in:
parent
9b7fd1a894
commit
111d33c123
@ -74,6 +74,19 @@
|
|||||||
<p>Improve TLS error reporting.</p>
|
<p>Improve TLS error reporting.</p>
|
||||||
</release-item>
|
</release-item>
|
||||||
</release-improvement-list>
|
</release-improvement-list>
|
||||||
|
|
||||||
|
<release-development-list>
|
||||||
|
<release-item>
|
||||||
|
<commit subject="Add IoClient and IoSession interfaces."/>
|
||||||
|
|
||||||
|
<release-item-contributor-list>
|
||||||
|
<release-item-reviewer id="stephen.frost"/>
|
||||||
|
<release-item-reviewer id="cynthia.shang"/>
|
||||||
|
</release-item-contributor-list>
|
||||||
|
|
||||||
|
<p>Allow <code>HttpClient</code>/<code>HttpSession</code> to work on plain sockets.</p>
|
||||||
|
</release-item>
|
||||||
|
</release-development-list>
|
||||||
</release-core-list>
|
</release-core-list>
|
||||||
|
|
||||||
<release-doc-list>
|
<release-doc-list>
|
||||||
|
@ -66,6 +66,7 @@ SRCS = \
|
|||||||
common/fork.c \
|
common/fork.c \
|
||||||
common/io/bufferRead.c \
|
common/io/bufferRead.c \
|
||||||
common/io/bufferWrite.c \
|
common/io/bufferWrite.c \
|
||||||
|
common/io/client.c \
|
||||||
common/io/fdRead.c \
|
common/io/fdRead.c \
|
||||||
common/io/fdWrite.c \
|
common/io/fdWrite.c \
|
||||||
common/io/filter/buffer.c \
|
common/io/filter/buffer.c \
|
||||||
@ -82,6 +83,7 @@ SRCS = \
|
|||||||
common/io/http/session.c \
|
common/io/http/session.c \
|
||||||
common/io/io.c \
|
common/io/io.c \
|
||||||
common/io/read.c \
|
common/io/read.c \
|
||||||
|
common/io/session.c \
|
||||||
common/io/socket/client.c \
|
common/io/socket/client.c \
|
||||||
common/io/socket/common.c \
|
common/io/socket/common.c \
|
||||||
common/io/socket/session.c \
|
common/io/socket/session.c \
|
||||||
|
69
src/common/io/client.c
Normal file
69
src/common/io/client.c
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
/***********************************************************************************************************************************
|
||||||
|
Io Client Interface
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
#include "build.auto.h"
|
||||||
|
|
||||||
|
#include "common/debug.h"
|
||||||
|
#include "common/io/client.intern.h"
|
||||||
|
#include "common/log.h"
|
||||||
|
#include "common/memContext.h"
|
||||||
|
#include "common/type/object.h"
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Object type
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
struct IoClient
|
||||||
|
{
|
||||||
|
MemContext *memContext; // Mem context
|
||||||
|
void *driver; // Driver object
|
||||||
|
const IoClientInterface *interface; // Driver interface
|
||||||
|
};
|
||||||
|
|
||||||
|
OBJECT_DEFINE_FREE(IO_CLIENT);
|
||||||
|
|
||||||
|
/**********************************************************************************************************************************/
|
||||||
|
IoClient *
|
||||||
|
ioClientNew(void *driver, const IoClientInterface *interface)
|
||||||
|
{
|
||||||
|
FUNCTION_LOG_BEGIN(logLevelTrace)
|
||||||
|
FUNCTION_LOG_PARAM_P(VOID, driver);
|
||||||
|
FUNCTION_LOG_PARAM(IO_CLIENT_INTERFACE, interface);
|
||||||
|
FUNCTION_LOG_END();
|
||||||
|
|
||||||
|
ASSERT(driver != NULL);
|
||||||
|
ASSERT(interface != NULL);
|
||||||
|
ASSERT(interface->type != NULL);
|
||||||
|
ASSERT(interface->open != NULL);
|
||||||
|
ASSERT(interface->toLog != NULL);
|
||||||
|
|
||||||
|
IoClient *this = memNew(sizeof(IoClient));
|
||||||
|
|
||||||
|
*this = (IoClient)
|
||||||
|
{
|
||||||
|
.memContext = memContextCurrent(),
|
||||||
|
.driver = driver,
|
||||||
|
.interface = interface,
|
||||||
|
};
|
||||||
|
|
||||||
|
FUNCTION_LOG_RETURN(IO_CLIENT, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************************************************************************************************************************/
|
||||||
|
IoSession *
|
||||||
|
ioClientOpen(IoClient *this)
|
||||||
|
{
|
||||||
|
FUNCTION_LOG_BEGIN(logLevelTrace);
|
||||||
|
FUNCTION_LOG_PARAM(IO_CLIENT, this);
|
||||||
|
FUNCTION_LOG_END();
|
||||||
|
|
||||||
|
ASSERT(this != NULL);
|
||||||
|
|
||||||
|
FUNCTION_LOG_RETURN(IO_SESSION, this->interface->open(this->driver));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************************************************************************************************************************/
|
||||||
|
String *
|
||||||
|
ioClientToLog(const IoClient *this)
|
||||||
|
{
|
||||||
|
return strNewFmt("{type: %s, driver: %s}", strZ(*this->interface->type), strZ(this->interface->toLog(this->driver)));
|
||||||
|
}
|
41
src/common/io/client.h
Normal file
41
src/common/io/client.h
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/***********************************************************************************************************************************
|
||||||
|
Io Client Interface
|
||||||
|
|
||||||
|
Create sessions for protocol clients. For example, a TLS client can be created with tlsClientNew() and then new TLS sessions can be
|
||||||
|
opened with ioClientOpen().
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
#ifndef COMMON_IO_CLIENT_H
|
||||||
|
#define COMMON_IO_CLIENT_H
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Object type
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
#define IO_CLIENT_TYPE IoClient
|
||||||
|
#define IO_CLIENT_PREFIX ioClient
|
||||||
|
|
||||||
|
typedef struct IoClient IoClient;
|
||||||
|
|
||||||
|
#include "common/io/session.h"
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Functions
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
// Open session
|
||||||
|
IoSession *ioClientOpen(IoClient *this);
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Destructor
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
void ioClientFree(IoClient *this);
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Macros for function logging
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
String *ioClientToLog(const IoClient *this);
|
||||||
|
|
||||||
|
#define FUNCTION_LOG_IO_CLIENT_TYPE \
|
||||||
|
IoClient *
|
||||||
|
#define FUNCTION_LOG_IO_CLIENT_FORMAT(value, buffer, bufferSize) \
|
||||||
|
FUNCTION_LOG_STRING_OBJECT_FORMAT(value, ioClientToLog, buffer, bufferSize)
|
||||||
|
|
||||||
|
#endif
|
38
src/common/io/client.intern.h
Normal file
38
src/common/io/client.intern.h
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
/***********************************************************************************************************************************
|
||||||
|
Io Client Interface Internal
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
#ifndef COMMON_IO_CLIENT_INTERN_H
|
||||||
|
#define COMMON_IO_CLIENT_INTERN_H
|
||||||
|
|
||||||
|
#include "common/io/client.h"
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Interface
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
typedef struct IoClientInterface
|
||||||
|
{
|
||||||
|
// Type used to identify the client. This is stored as a pointer to a String pointer so it can be used with an existing String
|
||||||
|
// constant (e.g. created with STRING_EXTERN()) without needing to be copied.
|
||||||
|
const String *const *type;
|
||||||
|
|
||||||
|
// Open a session
|
||||||
|
IoSession *(*open)(void *driver);
|
||||||
|
|
||||||
|
// Driver log function
|
||||||
|
String *(*toLog)(const void *driver);
|
||||||
|
} IoClientInterface;
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Constructors
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
IoClient *ioClientNew(void *driver, const IoClientInterface *interface);
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Macros for function logging
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
#define FUNCTION_LOG_IO_CLIENT_INTERFACE_TYPE \
|
||||||
|
IoClientInterface *
|
||||||
|
#define FUNCTION_LOG_IO_CLIENT_INTERFACE_FORMAT(value, buffer, bufferSize) \
|
||||||
|
objToLog(&value, "IoClientInterface", buffer, bufferSize)
|
||||||
|
|
||||||
|
#endif
|
@ -4,8 +4,8 @@ HTTP Client
|
|||||||
#include "build.auto.h"
|
#include "build.auto.h"
|
||||||
|
|
||||||
#include "common/debug.h"
|
#include "common/debug.h"
|
||||||
|
#include "common/io/client.h"
|
||||||
#include "common/io/http/client.h"
|
#include "common/io/http/client.h"
|
||||||
#include "common/io/tls/client.h"
|
|
||||||
#include "common/log.h"
|
#include "common/log.h"
|
||||||
#include "common/type/object.h"
|
#include "common/type/object.h"
|
||||||
|
|
||||||
@ -21,7 +21,7 @@ struct HttpClient
|
|||||||
{
|
{
|
||||||
MemContext *memContext; // Mem context
|
MemContext *memContext; // Mem context
|
||||||
TimeMSec timeout; // Request timeout
|
TimeMSec timeout; // Request timeout
|
||||||
TlsClient *tlsClient; // TLS client
|
IoClient *ioClient; // Io client (e.g. TLS or socket client)
|
||||||
|
|
||||||
List *sessionReuseList; // List of HTTP sessions that can be reused
|
List *sessionReuseList; // List of HTTP sessions that can be reused
|
||||||
};
|
};
|
||||||
@ -30,19 +30,14 @@ OBJECT_DEFINE_GET(Timeout, const, HTTP_CLIENT, TimeMSec, timeout);
|
|||||||
|
|
||||||
/**********************************************************************************************************************************/
|
/**********************************************************************************************************************************/
|
||||||
HttpClient *
|
HttpClient *
|
||||||
httpClientNew(
|
httpClientNew(IoClient *ioClient, TimeMSec timeout)
|
||||||
const String *host, unsigned int port, TimeMSec timeout, bool verifyPeer, const String *caFile, const String *caPath)
|
|
||||||
{
|
{
|
||||||
FUNCTION_LOG_BEGIN(logLevelDebug)
|
FUNCTION_LOG_BEGIN(logLevelDebug)
|
||||||
FUNCTION_LOG_PARAM(STRING, host);
|
FUNCTION_LOG_PARAM(IO_CLIENT, ioClient);
|
||||||
FUNCTION_LOG_PARAM(UINT, port);
|
|
||||||
FUNCTION_LOG_PARAM(TIME_MSEC, timeout);
|
FUNCTION_LOG_PARAM(TIME_MSEC, timeout);
|
||||||
FUNCTION_LOG_PARAM(BOOL, verifyPeer);
|
|
||||||
FUNCTION_LOG_PARAM(STRING, caFile);
|
|
||||||
FUNCTION_LOG_PARAM(STRING, caPath);
|
|
||||||
FUNCTION_LOG_END();
|
FUNCTION_LOG_END();
|
||||||
|
|
||||||
ASSERT(host != NULL);
|
ASSERT(ioClient != NULL);
|
||||||
|
|
||||||
HttpClient *this = NULL;
|
HttpClient *this = NULL;
|
||||||
|
|
||||||
@ -54,7 +49,7 @@ httpClientNew(
|
|||||||
{
|
{
|
||||||
.memContext = MEM_CONTEXT_NEW(),
|
.memContext = MEM_CONTEXT_NEW(),
|
||||||
.timeout = timeout,
|
.timeout = timeout,
|
||||||
.tlsClient = tlsClientNew(sckClientNew(host, port, timeout), timeout, verifyPeer, caFile, caPath),
|
.ioClient = ioClient,
|
||||||
.sessionReuseList = lstNewP(sizeof(HttpSession *)),
|
.sessionReuseList = lstNewP(sizeof(HttpSession *)),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -90,7 +85,7 @@ httpClientOpen(HttpClient *this)
|
|||||||
// Else create a new session
|
// Else create a new session
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result = httpSessionNew(this, tlsClientOpen(this->tlsClient));
|
result = httpSessionNew(this, ioClientOpen(this->ioClient));
|
||||||
httpClientStat.session++;
|
httpClientStat.session++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,6 +24,7 @@ Object type
|
|||||||
|
|
||||||
typedef struct HttpClient HttpClient;
|
typedef struct HttpClient HttpClient;
|
||||||
|
|
||||||
|
#include "common/io/client.h"
|
||||||
#include "common/io/http/session.h"
|
#include "common/io/http/session.h"
|
||||||
#include "common/time.h"
|
#include "common/time.h"
|
||||||
|
|
||||||
@ -33,7 +34,7 @@ Statistics
|
|||||||
typedef struct HttpClientStat
|
typedef struct HttpClientStat
|
||||||
{
|
{
|
||||||
uint64_t object; // Objects created
|
uint64_t object; // Objects created
|
||||||
uint64_t session; // TLS sessions created
|
uint64_t session; // Sessions created
|
||||||
uint64_t request; // Requests (i.e. calls to httpRequestNew())
|
uint64_t request; // Requests (i.e. calls to httpRequestNew())
|
||||||
uint64_t retry; // Request retries
|
uint64_t retry; // Request retries
|
||||||
uint64_t close; // Closes forced by server
|
uint64_t close; // Closes forced by server
|
||||||
@ -44,8 +45,7 @@ extern HttpClientStat httpClientStat;
|
|||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
Constructors
|
Constructors
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
HttpClient *httpClientNew(
|
HttpClient *httpClientNew(IoClient *ioClient, TimeMSec timeout);
|
||||||
const String *host, unsigned int port, TimeMSec timeout, bool verifyPeer, const String *caFile, const String *caPath);
|
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
Functions
|
Functions
|
||||||
|
@ -10,7 +10,6 @@ HTTP Response
|
|||||||
#include "common/io/http/response.h"
|
#include "common/io/http/response.h"
|
||||||
#include "common/io/io.h"
|
#include "common/io/io.h"
|
||||||
#include "common/io/read.intern.h"
|
#include "common/io/read.intern.h"
|
||||||
#include "common/io/tls/client.h"
|
|
||||||
#include "common/log.h"
|
#include "common/log.h"
|
||||||
#include "common/type/object.h"
|
#include "common/type/object.h"
|
||||||
#include "common/wait.h"
|
#include "common/wait.h"
|
||||||
|
@ -17,7 +17,7 @@ struct HttpSession
|
|||||||
{
|
{
|
||||||
MemContext *memContext; // Mem context
|
MemContext *memContext; // Mem context
|
||||||
HttpClient *httpClient; // HTTP client
|
HttpClient *httpClient; // HTTP client
|
||||||
TlsSession *tlsSession; // TLS session
|
IoSession *ioSession; // IO session
|
||||||
};
|
};
|
||||||
|
|
||||||
OBJECT_DEFINE_MOVE(HTTP_SESSION);
|
OBJECT_DEFINE_MOVE(HTTP_SESSION);
|
||||||
@ -25,15 +25,15 @@ OBJECT_DEFINE_FREE(HTTP_SESSION);
|
|||||||
|
|
||||||
/**********************************************************************************************************************************/
|
/**********************************************************************************************************************************/
|
||||||
HttpSession *
|
HttpSession *
|
||||||
httpSessionNew(HttpClient *httpClient, TlsSession *tlsSession)
|
httpSessionNew(HttpClient *httpClient, IoSession *ioSession)
|
||||||
{
|
{
|
||||||
FUNCTION_LOG_BEGIN(logLevelDebug)
|
FUNCTION_LOG_BEGIN(logLevelDebug)
|
||||||
FUNCTION_LOG_PARAM(HTTP_CLIENT, httpClient);
|
FUNCTION_LOG_PARAM(HTTP_CLIENT, httpClient);
|
||||||
FUNCTION_LOG_PARAM(TLS_SESSION, tlsSession);
|
FUNCTION_LOG_PARAM(IO_SESSION, ioSession);
|
||||||
FUNCTION_LOG_END();
|
FUNCTION_LOG_END();
|
||||||
|
|
||||||
ASSERT(httpClient != NULL);
|
ASSERT(httpClient != NULL);
|
||||||
ASSERT(tlsSession != NULL);
|
ASSERT(ioSession != NULL);
|
||||||
|
|
||||||
HttpSession *this = NULL;
|
HttpSession *this = NULL;
|
||||||
|
|
||||||
@ -45,7 +45,7 @@ httpSessionNew(HttpClient *httpClient, TlsSession *tlsSession)
|
|||||||
{
|
{
|
||||||
.memContext = MEM_CONTEXT_NEW(),
|
.memContext = MEM_CONTEXT_NEW(),
|
||||||
.httpClient = httpClient,
|
.httpClient = httpClient,
|
||||||
.tlsSession = tlsSessionMove(tlsSession, memContextCurrent()),
|
.ioSession = ioSessionMove(ioSession, memContextCurrent()),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
MEM_CONTEXT_NEW_END();
|
MEM_CONTEXT_NEW_END();
|
||||||
@ -78,7 +78,7 @@ httpSessionIoRead(HttpSession *this)
|
|||||||
|
|
||||||
ASSERT(this != NULL);
|
ASSERT(this != NULL);
|
||||||
|
|
||||||
FUNCTION_TEST_RETURN(tlsSessionIoRead(this->tlsSession));
|
FUNCTION_TEST_RETURN(ioSessionIoRead(this->ioSession));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**********************************************************************************************************************************/
|
/**********************************************************************************************************************************/
|
||||||
@ -91,5 +91,5 @@ httpSessionIoWrite(HttpSession *this)
|
|||||||
|
|
||||||
ASSERT(this != NULL);
|
ASSERT(this != NULL);
|
||||||
|
|
||||||
FUNCTION_TEST_RETURN(tlsSessionIoWrite(this->tlsSession));
|
FUNCTION_TEST_RETURN(ioSessionIoWrite(this->ioSession));
|
||||||
}
|
}
|
||||||
|
@ -16,13 +16,13 @@ typedef struct HttpSession HttpSession;
|
|||||||
|
|
||||||
#include "common/io/read.h"
|
#include "common/io/read.h"
|
||||||
#include "common/io/http/client.h"
|
#include "common/io/http/client.h"
|
||||||
#include "common/io/tls/session.h"
|
#include "common/io/session.h"
|
||||||
#include "common/io/write.h"
|
#include "common/io/write.h"
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
Constructors
|
Constructors
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
HttpSession *httpSessionNew(HttpClient *client, TlsSession *session);
|
HttpSession *httpSessionNew(HttpClient *client, IoSession *session);
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
Functions
|
Functions
|
||||||
|
100
src/common/io/session.c
Normal file
100
src/common/io/session.c
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
/***********************************************************************************************************************************
|
||||||
|
Io Session Interface
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
#include "build.auto.h"
|
||||||
|
|
||||||
|
#include "common/debug.h"
|
||||||
|
#include "common/io/session.intern.h"
|
||||||
|
#include "common/log.h"
|
||||||
|
#include "common/memContext.h"
|
||||||
|
#include "common/type/object.h"
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Object type
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
struct IoSession
|
||||||
|
{
|
||||||
|
MemContext *memContext; // Mem context
|
||||||
|
void *driver; // Driver object
|
||||||
|
const IoSessionInterface *interface; // Driver interface
|
||||||
|
};
|
||||||
|
|
||||||
|
OBJECT_DEFINE_MOVE(IO_SESSION);
|
||||||
|
OBJECT_DEFINE_FREE(IO_SESSION);
|
||||||
|
|
||||||
|
/**********************************************************************************************************************************/
|
||||||
|
IoSession *
|
||||||
|
ioSessionNew(void *driver, const IoSessionInterface *interface)
|
||||||
|
{
|
||||||
|
FUNCTION_LOG_BEGIN(logLevelTrace)
|
||||||
|
FUNCTION_LOG_PARAM_P(VOID, driver);
|
||||||
|
FUNCTION_LOG_PARAM(IO_SESSION_INTERFACE, interface);
|
||||||
|
FUNCTION_LOG_END();
|
||||||
|
|
||||||
|
ASSERT(driver != NULL);
|
||||||
|
ASSERT(interface != NULL);
|
||||||
|
ASSERT(interface->type != NULL);
|
||||||
|
ASSERT(interface->close != NULL);
|
||||||
|
ASSERT(interface->ioRead != NULL);
|
||||||
|
ASSERT(interface->ioWrite != NULL);
|
||||||
|
ASSERT(interface->toLog != NULL);
|
||||||
|
|
||||||
|
IoSession *this = memNew(sizeof(IoSession));
|
||||||
|
|
||||||
|
*this = (IoSession)
|
||||||
|
{
|
||||||
|
.memContext = memContextCurrent(),
|
||||||
|
.driver = driver,
|
||||||
|
.interface = interface,
|
||||||
|
};
|
||||||
|
|
||||||
|
FUNCTION_LOG_RETURN(IO_SESSION, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************************************************************************************************************************/
|
||||||
|
void
|
||||||
|
ioSessionClose(IoSession *this)
|
||||||
|
{
|
||||||
|
FUNCTION_LOG_BEGIN(logLevelTrace);
|
||||||
|
FUNCTION_LOG_PARAM(IO_SESSION, this);
|
||||||
|
FUNCTION_LOG_END();
|
||||||
|
|
||||||
|
ASSERT(this != NULL);
|
||||||
|
|
||||||
|
this->interface->close(this->driver);
|
||||||
|
|
||||||
|
FUNCTION_LOG_RETURN_VOID();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************************************************************************************************************************/
|
||||||
|
IoRead *
|
||||||
|
ioSessionIoRead(IoSession *this)
|
||||||
|
{
|
||||||
|
FUNCTION_TEST_BEGIN();
|
||||||
|
FUNCTION_TEST_PARAM(IO_SESSION, this);
|
||||||
|
FUNCTION_TEST_END();
|
||||||
|
|
||||||
|
ASSERT(this != NULL);
|
||||||
|
|
||||||
|
FUNCTION_TEST_RETURN(this->interface->ioRead(this->driver));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************************************************************************************************************************/
|
||||||
|
IoWrite *
|
||||||
|
ioSessionIoWrite(IoSession *this)
|
||||||
|
{
|
||||||
|
FUNCTION_TEST_BEGIN();
|
||||||
|
FUNCTION_TEST_PARAM(IO_SESSION, this);
|
||||||
|
FUNCTION_TEST_END();
|
||||||
|
|
||||||
|
ASSERT(this != NULL);
|
||||||
|
|
||||||
|
FUNCTION_TEST_RETURN(this->interface->ioWrite(this->driver));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************************************************************************************************************************/
|
||||||
|
String *
|
||||||
|
ioSessionToLog(const IoSession *this)
|
||||||
|
{
|
||||||
|
return strNewFmt("{type: %s, driver: %s}", strZ(*this->interface->type), strZ(this->interface->toLog(this->driver)));
|
||||||
|
}
|
54
src/common/io/session.h
Normal file
54
src/common/io/session.h
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
/***********************************************************************************************************************************
|
||||||
|
Io Session Interface
|
||||||
|
|
||||||
|
Provides access to IoRead and IoWrite interfaces for interacting with the session returned by ioClientOpen(). Sessions should always
|
||||||
|
be closed when work with them is done but they also contain destructors to do cleanup if there is an error.
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
#ifndef COMMON_IO_SESSION_H
|
||||||
|
#define COMMON_IO_SESSION_H
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Object type
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
#define IO_SESSION_TYPE IoSession
|
||||||
|
#define IO_SESSION_PREFIX ioSession
|
||||||
|
|
||||||
|
typedef struct IoSession IoSession;
|
||||||
|
|
||||||
|
#include "common/io/read.h"
|
||||||
|
#include "common/io/write.h"
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Functions
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
// Close the session
|
||||||
|
void ioSessionClose(IoSession *this);
|
||||||
|
|
||||||
|
// Move to a new parent mem context
|
||||||
|
IoSession *ioSessionMove(IoSession *this, MemContext *parentNew);
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Getters/Setters
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
// Read interface
|
||||||
|
IoRead *ioSessionIoRead(IoSession *this);
|
||||||
|
|
||||||
|
// Write interface
|
||||||
|
IoWrite *ioSessionIoWrite(IoSession *this);
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Destructor
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
void ioSessionFree(IoSession *this);
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Macros for function logging
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
String *ioSessionToLog(const IoSession *this);
|
||||||
|
|
||||||
|
#define FUNCTION_LOG_IO_SESSION_TYPE \
|
||||||
|
IoSession *
|
||||||
|
#define FUNCTION_LOG_IO_SESSION_FORMAT(value, buffer, bufferSize) \
|
||||||
|
FUNCTION_LOG_STRING_OBJECT_FORMAT(value, ioSessionToLog, buffer, bufferSize)
|
||||||
|
|
||||||
|
#endif
|
44
src/common/io/session.intern.h
Normal file
44
src/common/io/session.intern.h
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
/***********************************************************************************************************************************
|
||||||
|
Io Session Interface Internal
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
#ifndef COMMON_IO_SESSION_INTERN_H
|
||||||
|
#define COMMON_IO_SESSION_INTERN_H
|
||||||
|
|
||||||
|
#include "common/io/session.h"
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Interface
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
typedef struct IoSessionInterface
|
||||||
|
{
|
||||||
|
// Type used to identify the session. This is stored as a pointer to a String pointer so it can be used with an existing String
|
||||||
|
// constant (e.g. created with STRING_EXTERN()) without needing to be copied.
|
||||||
|
const String *const *type;
|
||||||
|
|
||||||
|
// Close the session
|
||||||
|
void (*close)(void *driver);
|
||||||
|
|
||||||
|
// IoRead interface for the session
|
||||||
|
IoRead *(*ioRead)(void *driver);
|
||||||
|
|
||||||
|
// IoWrite interface for the session
|
||||||
|
IoWrite *(*ioWrite)(void *driver);
|
||||||
|
|
||||||
|
// Driver log function
|
||||||
|
String *(*toLog)(const void *driver);
|
||||||
|
} IoSessionInterface;
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Constructors
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
IoSession *ioSessionNew(void *driver, const IoSessionInterface *interface);
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Macros for function logging
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
#define FUNCTION_LOG_IO_SESSION_INTERFACE_TYPE \
|
||||||
|
IoSessionInterface *
|
||||||
|
#define FUNCTION_LOG_IO_SESSION_INTERFACE_FORMAT(value, buffer, bufferSize) \
|
||||||
|
objToLog(&value, "IoSessionInterface", buffer, bufferSize)
|
||||||
|
|
||||||
|
#endif
|
@ -11,13 +11,19 @@ TLS Client
|
|||||||
#include "common/crypto/common.h"
|
#include "common/crypto/common.h"
|
||||||
#include "common/debug.h"
|
#include "common/debug.h"
|
||||||
#include "common/log.h"
|
#include "common/log.h"
|
||||||
|
#include "common/io/client.intern.h"
|
||||||
#include "common/io/io.h"
|
#include "common/io/io.h"
|
||||||
#include "common/io/tls/client.h"
|
#include "common/io/tls/client.h"
|
||||||
#include "common/io/tls/session.intern.h"
|
#include "common/io/tls/session.h"
|
||||||
#include "common/memContext.h"
|
#include "common/memContext.h"
|
||||||
#include "common/type/object.h"
|
#include "common/type/object.h"
|
||||||
#include "common/wait.h"
|
#include "common/wait.h"
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Io client type
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
STRING_EXTERN(IO_CLIENT_TLS_TYPE_STR, IO_CLIENT_TLS_TYPE);
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
Statistics
|
Statistics
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
@ -26,7 +32,10 @@ static TlsClientStat tlsClientStatLocal;
|
|||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
Object type
|
Object type
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
struct TlsClient
|
#define TLS_CLIENT_TYPE TlsClient
|
||||||
|
#define TLS_CLIENT_PREFIX tlsClient
|
||||||
|
|
||||||
|
typedef struct TlsClient
|
||||||
{
|
{
|
||||||
MemContext *memContext; // Mem context
|
MemContext *memContext; // Mem context
|
||||||
TimeMSec timeout; // Timeout for any i/o operation (connect, read, etc.)
|
TimeMSec timeout; // Timeout for any i/o operation (connect, read, etc.)
|
||||||
@ -34,9 +43,26 @@ struct TlsClient
|
|||||||
SocketClient *socketClient; // Socket client
|
SocketClient *socketClient; // Socket client
|
||||||
|
|
||||||
SSL_CTX *context; // TLS context
|
SSL_CTX *context; // TLS context
|
||||||
};
|
} TlsClient;
|
||||||
|
|
||||||
OBJECT_DEFINE_FREE(TLS_CLIENT);
|
/***********************************************************************************************************************************
|
||||||
|
Macros for function logging
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
static String *
|
||||||
|
tlsClientToLog(const THIS_VOID)
|
||||||
|
{
|
||||||
|
THIS(const TlsClient);
|
||||||
|
|
||||||
|
return strNewFmt(
|
||||||
|
"{socketClient: %s, timeout: %" PRIu64", verifyPeer: %s}",
|
||||||
|
memContextFreeing(this->memContext) ? NULL_Z : strZ(sckClientToLog(this->socketClient)), this->timeout,
|
||||||
|
cvtBoolToConstZ(this->verifyPeer));
|
||||||
|
}
|
||||||
|
|
||||||
|
#define FUNCTION_LOG_TLS_CLIENT_TYPE \
|
||||||
|
TlsClient *
|
||||||
|
#define FUNCTION_LOG_TLS_CLIENT_FORMAT(value, buffer, bufferSize) \
|
||||||
|
FUNCTION_LOG_STRING_OBJECT_FORMAT(value, tlsClientToLog, buffer, bufferSize)
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
Free connection
|
Free connection
|
||||||
@ -47,78 +73,6 @@ OBJECT_DEFINE_FREE_RESOURCE_BEGIN(TLS_CLIENT, LOG, logLevelTrace)
|
|||||||
}
|
}
|
||||||
OBJECT_DEFINE_FREE_RESOURCE_END(LOG);
|
OBJECT_DEFINE_FREE_RESOURCE_END(LOG);
|
||||||
|
|
||||||
/**********************************************************************************************************************************/
|
|
||||||
TlsClient *
|
|
||||||
tlsClientNew(SocketClient *socket, TimeMSec timeout, bool verifyPeer, const String *caFile, const String *caPath)
|
|
||||||
{
|
|
||||||
FUNCTION_LOG_BEGIN(logLevelDebug)
|
|
||||||
FUNCTION_LOG_PARAM(SOCKET_CLIENT, socket);
|
|
||||||
FUNCTION_LOG_PARAM(TIME_MSEC, timeout);
|
|
||||||
FUNCTION_LOG_PARAM(BOOL, verifyPeer);
|
|
||||||
FUNCTION_LOG_PARAM(STRING, caFile);
|
|
||||||
FUNCTION_LOG_PARAM(STRING, caPath);
|
|
||||||
FUNCTION_LOG_END();
|
|
||||||
|
|
||||||
ASSERT(socket != NULL);
|
|
||||||
|
|
||||||
TlsClient *this = NULL;
|
|
||||||
|
|
||||||
MEM_CONTEXT_NEW_BEGIN("TlsClient")
|
|
||||||
{
|
|
||||||
this = memNew(sizeof(TlsClient));
|
|
||||||
|
|
||||||
*this = (TlsClient)
|
|
||||||
{
|
|
||||||
.memContext = MEM_CONTEXT_NEW(),
|
|
||||||
.socketClient = sckClientMove(socket, MEM_CONTEXT_NEW()),
|
|
||||||
.timeout = timeout,
|
|
||||||
.verifyPeer = verifyPeer,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Setup TLS context
|
|
||||||
// -------------------------------------------------------------------------------------------------------------------------
|
|
||||||
cryptoInit();
|
|
||||||
|
|
||||||
// Select the TLS method to use. To maintain compatibility with older versions of OpenSSL we need to use an SSL method,
|
|
||||||
// but SSL versions will be excluded in SSL_CTX_set_options().
|
|
||||||
const SSL_METHOD *method = SSLv23_method();
|
|
||||||
cryptoError(method == NULL, "unable to load TLS method");
|
|
||||||
|
|
||||||
// Create the TLS context
|
|
||||||
this->context = SSL_CTX_new(method);
|
|
||||||
cryptoError(this->context == NULL, "unable to create TLS context");
|
|
||||||
|
|
||||||
memContextCallbackSet(this->memContext, tlsClientFreeResource, this);
|
|
||||||
|
|
||||||
// Exclude SSL versions to only allow TLS and also disable compression
|
|
||||||
SSL_CTX_set_options(this->context, (long)(SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION));
|
|
||||||
|
|
||||||
// Disable auto-retry to prevent SSL_read() from hanging
|
|
||||||
SSL_CTX_clear_mode(this->context, SSL_MODE_AUTO_RETRY);
|
|
||||||
|
|
||||||
// Set location of CA certificates if the server certificate will be verified
|
|
||||||
// -------------------------------------------------------------------------------------------------------------------------
|
|
||||||
if (this->verifyPeer)
|
|
||||||
{
|
|
||||||
// If the user specified a location
|
|
||||||
if (caFile != NULL || caPath != NULL) // {vm_covered}
|
|
||||||
{
|
|
||||||
cryptoError( // {vm_covered}
|
|
||||||
SSL_CTX_load_verify_locations(this->context, strZNull(caFile), strZNull(caPath)) != 1, // {vm_covered}
|
|
||||||
"unable to set user-defined CA certificate location"); // {vm_covered}
|
|
||||||
}
|
|
||||||
// Else use the defaults
|
|
||||||
else
|
|
||||||
cryptoError(SSL_CTX_set_default_verify_paths(this->context) != 1, "unable to set default CA certificate location");
|
|
||||||
}
|
|
||||||
|
|
||||||
tlsClientStatLocal.object++;
|
|
||||||
}
|
|
||||||
MEM_CONTEXT_NEW_END();
|
|
||||||
|
|
||||||
FUNCTION_LOG_RETURN(TLS_CLIENT, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
Convert an ASN1 string used in certificates to a String
|
Convert an ASN1 string used in certificates to a String
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
@ -259,16 +213,18 @@ tlsClientHostVerify(const String *host, X509 *certificate)
|
|||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
Open connection if this is a new client or if the connection was closed by the server
|
Open connection if this is a new client or if the connection was closed by the server
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
TlsSession *
|
static IoSession *
|
||||||
tlsClientOpen(TlsClient *this)
|
tlsClientOpen(THIS_VOID)
|
||||||
{
|
{
|
||||||
|
THIS(TlsClient);
|
||||||
|
|
||||||
FUNCTION_LOG_BEGIN(logLevelTrace)
|
FUNCTION_LOG_BEGIN(logLevelTrace)
|
||||||
FUNCTION_LOG_PARAM(TLS_CLIENT, this);
|
FUNCTION_LOG_PARAM(TLS_CLIENT, this);
|
||||||
FUNCTION_LOG_END();
|
FUNCTION_LOG_END();
|
||||||
|
|
||||||
ASSERT(this != NULL);
|
ASSERT(this != NULL);
|
||||||
|
|
||||||
TlsSession *result = NULL;
|
IoSession *result = NULL;
|
||||||
SSL *session = NULL;
|
SSL *session = NULL;
|
||||||
|
|
||||||
MEM_CONTEXT_TEMP_BEGIN()
|
MEM_CONTEXT_TEMP_BEGIN()
|
||||||
@ -317,7 +273,7 @@ tlsClientOpen(TlsClient *this)
|
|||||||
}
|
}
|
||||||
while (retry);
|
while (retry);
|
||||||
|
|
||||||
tlsSessionMove(result, memContextPrior());
|
ioSessionMove(result, memContextPrior());
|
||||||
}
|
}
|
||||||
MEM_CONTEXT_TEMP_END();
|
MEM_CONTEXT_TEMP_END();
|
||||||
|
|
||||||
@ -351,7 +307,92 @@ tlsClientOpen(TlsClient *this)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FUNCTION_LOG_RETURN(TLS_SESSION, result);
|
FUNCTION_LOG_RETURN(IO_SESSION, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************************************************************************************************************************/
|
||||||
|
static const IoClientInterface tlsClientInterface =
|
||||||
|
{
|
||||||
|
.type = &IO_CLIENT_TLS_TYPE_STR,
|
||||||
|
.open = tlsClientOpen,
|
||||||
|
.toLog = tlsClientToLog,
|
||||||
|
};
|
||||||
|
|
||||||
|
IoClient *
|
||||||
|
tlsClientNew(SocketClient *socket, TimeMSec timeout, bool verifyPeer, const String *caFile, const String *caPath)
|
||||||
|
{
|
||||||
|
FUNCTION_LOG_BEGIN(logLevelDebug)
|
||||||
|
FUNCTION_LOG_PARAM(SOCKET_CLIENT, socket);
|
||||||
|
FUNCTION_LOG_PARAM(TIME_MSEC, timeout);
|
||||||
|
FUNCTION_LOG_PARAM(BOOL, verifyPeer);
|
||||||
|
FUNCTION_LOG_PARAM(STRING, caFile);
|
||||||
|
FUNCTION_LOG_PARAM(STRING, caPath);
|
||||||
|
FUNCTION_LOG_END();
|
||||||
|
|
||||||
|
ASSERT(socket != NULL);
|
||||||
|
|
||||||
|
IoClient *this = NULL;
|
||||||
|
|
||||||
|
MEM_CONTEXT_NEW_BEGIN("TlsClient")
|
||||||
|
{
|
||||||
|
TlsClient *driver = memNew(sizeof(TlsClient));
|
||||||
|
|
||||||
|
*driver = (TlsClient)
|
||||||
|
{
|
||||||
|
.memContext = MEM_CONTEXT_NEW(),
|
||||||
|
.socketClient = sckClientMove(socket, MEM_CONTEXT_NEW()),
|
||||||
|
.timeout = timeout,
|
||||||
|
.verifyPeer = verifyPeer,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Setup TLS context
|
||||||
|
// -------------------------------------------------------------------------------------------------------------------------
|
||||||
|
cryptoInit();
|
||||||
|
|
||||||
|
// Select the TLS method to use. To maintain compatibility with older versions of OpenSSL we need to use an SSL method,
|
||||||
|
// but SSL versions will be excluded in SSL_CTX_set_options().
|
||||||
|
const SSL_METHOD *method = SSLv23_method();
|
||||||
|
cryptoError(method == NULL, "unable to load TLS method");
|
||||||
|
|
||||||
|
// Create the TLS context
|
||||||
|
driver->context = SSL_CTX_new(method);
|
||||||
|
cryptoError(driver->context == NULL, "unable to create TLS context");
|
||||||
|
|
||||||
|
memContextCallbackSet(driver->memContext, tlsClientFreeResource, driver);
|
||||||
|
|
||||||
|
// Exclude SSL versions to only allow TLS and also disable compression
|
||||||
|
SSL_CTX_set_options(driver->context, (long)(SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION));
|
||||||
|
|
||||||
|
// Disable auto-retry to prevent SSL_read() from hanging
|
||||||
|
SSL_CTX_clear_mode(driver->context, SSL_MODE_AUTO_RETRY);
|
||||||
|
|
||||||
|
// Set location of CA certificates if the server certificate will be verified
|
||||||
|
// -------------------------------------------------------------------------------------------------------------------------
|
||||||
|
if (driver->verifyPeer)
|
||||||
|
{
|
||||||
|
// If the user specified a location
|
||||||
|
if (caFile != NULL || caPath != NULL) // {vm_covered}
|
||||||
|
{
|
||||||
|
cryptoError( // {vm_covered}
|
||||||
|
SSL_CTX_load_verify_locations(driver->context, strZNull(caFile), strZNull(caPath)) != 1, // {vm_covered}
|
||||||
|
"unable to set user-defined CA certificate location"); // {vm_covered}
|
||||||
|
}
|
||||||
|
// Else use the defaults
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cryptoError(
|
||||||
|
SSL_CTX_set_default_verify_paths(driver->context) != 1, "unable to set default CA certificate location");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tlsClientStatLocal.object++;
|
||||||
|
|
||||||
|
// Create client interface
|
||||||
|
this = ioClientNew(driver, &tlsClientInterface);
|
||||||
|
}
|
||||||
|
MEM_CONTEXT_NEW_END();
|
||||||
|
|
||||||
|
FUNCTION_LOG_RETURN(IO_CLIENT, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**********************************************************************************************************************************/
|
/**********************************************************************************************************************************/
|
||||||
|
@ -4,21 +4,19 @@ TLS Client
|
|||||||
A simple, secure TLS client intended to allow access to services that are exposed via HTTPS. We call it TLS instead of SSL because
|
A simple, secure TLS client intended to allow access to services that are exposed via HTTPS. We call it TLS instead of SSL because
|
||||||
SSL methods are disabled so only TLS connections are allowed.
|
SSL methods are disabled so only TLS connections are allowed.
|
||||||
|
|
||||||
This object is intended to be used for multiple TLS sessions so tlsClientOpen() can be called each time a new session is needed.
|
This object is intended to be used for multiple TLS sessions so ioClientOpen() can be called each time a new session is needed.
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
#ifndef COMMON_IO_TLS_CLIENT_H
|
#ifndef COMMON_IO_TLS_CLIENT_H
|
||||||
#define COMMON_IO_TLS_CLIENT_H
|
#define COMMON_IO_TLS_CLIENT_H
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
#include "common/io/client.h"
|
||||||
Object type
|
|
||||||
***********************************************************************************************************************************/
|
|
||||||
#define TLS_CLIENT_TYPE TlsClient
|
|
||||||
#define TLS_CLIENT_PREFIX tlsClient
|
|
||||||
|
|
||||||
typedef struct TlsClient TlsClient;
|
|
||||||
|
|
||||||
#include "common/io/socket/client.h"
|
#include "common/io/socket/client.h"
|
||||||
#include "common/io/tls/session.h"
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Io client type
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
#define IO_CLIENT_TLS_TYPE "tls"
|
||||||
|
STRING_DECLARE(IO_CLIENT_TLS_TYPE_STR);
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
Statistics
|
Statistics
|
||||||
@ -33,28 +31,12 @@ typedef struct TlsClientStat
|
|||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
Constructors
|
Constructors
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
TlsClient *tlsClientNew(SocketClient *socket, TimeMSec timeout, bool verifyPeer, const String *caFile, const String *caPath);
|
IoClient *tlsClientNew(SocketClient *socket, TimeMSec timeout, bool verifyPeer, const String *caFile, const String *caPath);
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
Functions
|
Functions
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
// Open tls session
|
|
||||||
TlsSession *tlsClientOpen(TlsClient *this);
|
|
||||||
|
|
||||||
// Statistics as a formatted string
|
// Statistics as a formatted string
|
||||||
String *tlsClientStatStr(void);
|
String *tlsClientStatStr(void);
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
|
||||||
Destructor
|
|
||||||
***********************************************************************************************************************************/
|
|
||||||
void tlsClientFree(TlsClient *this);
|
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
|
||||||
Macros for function logging
|
|
||||||
***********************************************************************************************************************************/
|
|
||||||
#define FUNCTION_LOG_TLS_CLIENT_TYPE \
|
|
||||||
TlsClient *
|
|
||||||
#define FUNCTION_LOG_TLS_CLIENT_FORMAT(value, buffer, bufferSize) \
|
|
||||||
objToLog(value, "TlsClient", buffer, bufferSize)
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -9,7 +9,10 @@ TLS Session
|
|||||||
#include "common/debug.h"
|
#include "common/debug.h"
|
||||||
#include "common/io/io.h"
|
#include "common/io/io.h"
|
||||||
#include "common/io/read.intern.h"
|
#include "common/io/read.intern.h"
|
||||||
#include "common/io/tls/session.intern.h"
|
#include "common/io/session.intern.h"
|
||||||
|
#include "common/io/socket/session.h"
|
||||||
|
#include "common/io/tls/client.h"
|
||||||
|
#include "common/io/tls/session.h"
|
||||||
#include "common/io/write.intern.h"
|
#include "common/io/write.intern.h"
|
||||||
#include "common/log.h"
|
#include "common/log.h"
|
||||||
#include "common/memContext.h"
|
#include "common/memContext.h"
|
||||||
@ -18,23 +21,39 @@ TLS Session
|
|||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
Object type
|
Object type
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
struct TlsSession
|
#define TLS_SESSION_TYPE TlsSession
|
||||||
|
#define TLS_SESSION_PREFIX tlsSession
|
||||||
|
|
||||||
|
typedef struct TlsSession
|
||||||
{
|
{
|
||||||
MemContext *memContext; // Mem context
|
MemContext *memContext; // Mem context
|
||||||
SocketSession *socketSession; // Socket session
|
SocketSession *socketSession; // Socket session
|
||||||
SSL *session; // TLS session on the socket
|
SSL *session; // TLS session on the socket
|
||||||
TimeMSec timeout; // Timeout for any i/o operation (connect, read, etc.)
|
TimeMSec timeout; // Timeout for any i/o operation (connect, read, etc.)
|
||||||
|
bool shutdownOnClose; // Shutdown the TLS connection when closing the socket
|
||||||
|
|
||||||
IoRead *read; // Read interface
|
IoRead *read; // Read interface
|
||||||
IoWrite *write; // Write interface
|
IoWrite *write; // Write interface
|
||||||
};
|
} TlsSession;
|
||||||
|
|
||||||
OBJECT_DEFINE_MOVE(TLS_SESSION);
|
/***********************************************************************************************************************************
|
||||||
|
Macros for function logging
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
static String *
|
||||||
|
tlsSessionToLog(const THIS_VOID)
|
||||||
|
{
|
||||||
|
THIS(const TlsSession);
|
||||||
|
|
||||||
OBJECT_DEFINE_GET(IoRead, , TLS_SESSION, IoRead *, read);
|
return strNewFmt(
|
||||||
OBJECT_DEFINE_GET(IoWrite, , TLS_SESSION, IoWrite *, write);
|
"{socketSession: %s, timeout: %" PRIu64", shutdownOnClose: %s}",
|
||||||
|
this->socketSession == NULL || memContextFreeing(this->memContext) ? NULL_Z : strZ(sckSessionToLog(this->socketSession)),
|
||||||
|
this->timeout, cvtBoolToConstZ(this->shutdownOnClose));
|
||||||
|
}
|
||||||
|
|
||||||
OBJECT_DEFINE_FREE(TLS_SESSION);
|
#define FUNCTION_LOG_TLS_SESSION_TYPE \
|
||||||
|
TlsSession *
|
||||||
|
#define FUNCTION_LOG_TLS_SESSION_FORMAT(value, buffer, bufferSize) \
|
||||||
|
FUNCTION_LOG_STRING_OBJECT_FORMAT(value, tlsSessionToLog, buffer, bufferSize)
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
Free connection
|
Free connection
|
||||||
@ -46,12 +65,13 @@ OBJECT_DEFINE_FREE_RESOURCE_BEGIN(TLS_SESSION, LOG, logLevelTrace)
|
|||||||
OBJECT_DEFINE_FREE_RESOURCE_END(LOG);
|
OBJECT_DEFINE_FREE_RESOURCE_END(LOG);
|
||||||
|
|
||||||
/**********************************************************************************************************************************/
|
/**********************************************************************************************************************************/
|
||||||
void
|
static void
|
||||||
tlsSessionClose(TlsSession *this, bool shutdown)
|
tlsSessionClose(THIS_VOID)
|
||||||
{
|
{
|
||||||
|
THIS(TlsSession);
|
||||||
|
|
||||||
FUNCTION_LOG_BEGIN(logLevelTrace);
|
FUNCTION_LOG_BEGIN(logLevelTrace);
|
||||||
FUNCTION_LOG_PARAM(TLS_SESSION, this);
|
FUNCTION_LOG_PARAM(TLS_SESSION, this);
|
||||||
FUNCTION_LOG_PARAM(BOOL, shutdown);
|
|
||||||
FUNCTION_LOG_END();
|
FUNCTION_LOG_END();
|
||||||
|
|
||||||
ASSERT(this != NULL);
|
ASSERT(this != NULL);
|
||||||
@ -60,7 +80,7 @@ tlsSessionClose(TlsSession *this, bool shutdown)
|
|||||||
if (this->session != NULL)
|
if (this->session != NULL)
|
||||||
{
|
{
|
||||||
// Shutdown on request
|
// Shutdown on request
|
||||||
if (shutdown)
|
if (this->shutdownOnClose)
|
||||||
SSL_shutdown(this->session);
|
SSL_shutdown(this->session);
|
||||||
|
|
||||||
// Free the socket session
|
// Free the socket session
|
||||||
@ -109,7 +129,8 @@ tlsSessionResultProcess(TlsSession *this, int errorTls, long unsigned int errorT
|
|||||||
if (!closeOk)
|
if (!closeOk)
|
||||||
THROW(ProtocolError, "unexpected TLS eof");
|
THROW(ProtocolError, "unexpected TLS eof");
|
||||||
|
|
||||||
tlsSessionClose(this, false);
|
this->shutdownOnClose = false;
|
||||||
|
tlsSessionClose(this);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -272,7 +293,46 @@ tlsSessionEof(THIS_VOID)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**********************************************************************************************************************************/
|
/**********************************************************************************************************************************/
|
||||||
TlsSession *
|
static IoRead *
|
||||||
|
tlsSessionIoRead(THIS_VOID)
|
||||||
|
{
|
||||||
|
THIS(TlsSession);
|
||||||
|
|
||||||
|
FUNCTION_TEST_BEGIN();
|
||||||
|
FUNCTION_TEST_PARAM(TLS_SESSION, this);
|
||||||
|
FUNCTION_TEST_END();
|
||||||
|
|
||||||
|
ASSERT(this != NULL);
|
||||||
|
|
||||||
|
FUNCTION_TEST_RETURN(this->read);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************************************************************************************************************************/
|
||||||
|
static IoWrite *
|
||||||
|
tlsSessionIoWrite(THIS_VOID)
|
||||||
|
{
|
||||||
|
THIS(TlsSession);
|
||||||
|
|
||||||
|
FUNCTION_TEST_BEGIN();
|
||||||
|
FUNCTION_TEST_PARAM(TLS_SESSION, this);
|
||||||
|
FUNCTION_TEST_END();
|
||||||
|
|
||||||
|
ASSERT(this != NULL);
|
||||||
|
|
||||||
|
FUNCTION_TEST_RETURN(this->write);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************************************************************************************************************************/
|
||||||
|
static const IoSessionInterface tlsSessionInterface =
|
||||||
|
{
|
||||||
|
.type = &IO_CLIENT_TLS_TYPE_STR,
|
||||||
|
.close = tlsSessionClose,
|
||||||
|
.ioRead = tlsSessionIoRead,
|
||||||
|
.ioWrite = tlsSessionIoWrite,
|
||||||
|
.toLog = tlsSessionToLog,
|
||||||
|
};
|
||||||
|
|
||||||
|
IoSession *
|
||||||
tlsSessionNew(SSL *session, SocketSession *socketSession, TimeMSec timeout)
|
tlsSessionNew(SSL *session, SocketSession *socketSession, TimeMSec timeout)
|
||||||
{
|
{
|
||||||
FUNCTION_LOG_BEGIN(logLevelDebug)
|
FUNCTION_LOG_BEGIN(logLevelDebug)
|
||||||
@ -284,26 +344,27 @@ tlsSessionNew(SSL *session, SocketSession *socketSession, TimeMSec timeout)
|
|||||||
ASSERT(session != NULL);
|
ASSERT(session != NULL);
|
||||||
ASSERT(socketSession != NULL);
|
ASSERT(socketSession != NULL);
|
||||||
|
|
||||||
TlsSession *this = NULL;
|
IoSession *this = NULL;
|
||||||
|
|
||||||
MEM_CONTEXT_NEW_BEGIN("TlsSession")
|
MEM_CONTEXT_NEW_BEGIN("TlsSession")
|
||||||
{
|
{
|
||||||
this = memNew(sizeof(TlsSession));
|
TlsSession *driver = memNew(sizeof(TlsSession));
|
||||||
|
|
||||||
*this = (TlsSession)
|
*driver = (TlsSession)
|
||||||
{
|
{
|
||||||
.memContext = MEM_CONTEXT_NEW(),
|
.memContext = MEM_CONTEXT_NEW(),
|
||||||
.session = session,
|
.session = session,
|
||||||
.socketSession = sckSessionMove(socketSession, MEM_CONTEXT_NEW()),
|
.socketSession = sckSessionMove(socketSession, MEM_CONTEXT_NEW()),
|
||||||
.timeout = timeout,
|
.timeout = timeout,
|
||||||
|
.shutdownOnClose = true,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Ensure session is freed
|
// Ensure session is freed
|
||||||
memContextCallbackSet(this->memContext, tlsSessionFreeResource, this);
|
memContextCallbackSet(driver->memContext, tlsSessionFreeResource, driver);
|
||||||
|
|
||||||
// Assign socket to TLS session
|
// Assign socket to TLS session
|
||||||
cryptoError(
|
cryptoError(
|
||||||
SSL_set_fd(this->session, sckSessionFd(this->socketSession)) != 1, "unable to add socket to TLS session");
|
SSL_set_fd(driver->session, sckSessionFd(driver->socketSession)) != 1, "unable to add socket to TLS session");
|
||||||
|
|
||||||
// Negotiate TLS session. The error queue must be cleared before this operation.
|
// Negotiate TLS session. The error queue must be cleared before this operation.
|
||||||
int result = 0;
|
int result = 0;
|
||||||
@ -312,19 +373,22 @@ tlsSessionNew(SSL *session, SocketSession *socketSession, TimeMSec timeout)
|
|||||||
{
|
{
|
||||||
ERR_clear_error();
|
ERR_clear_error();
|
||||||
|
|
||||||
if (sckSessionType(this->socketSession) == sckSessionTypeClient)
|
if (sckSessionType(driver->socketSession) == sckSessionTypeClient)
|
||||||
result = tlsSessionResult(this, SSL_connect(this->session), false);
|
result = tlsSessionResult(driver, SSL_connect(driver->session), false);
|
||||||
else
|
else
|
||||||
result = tlsSessionResult(this, SSL_accept(this->session), false);
|
result = tlsSessionResult(driver, SSL_accept(driver->session), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create read and write interfaces
|
// Create read and write interfaces
|
||||||
this->write = ioWriteNewP(this, .write = tlsSessionWrite);
|
driver->write = ioWriteNewP(driver, .write = tlsSessionWrite);
|
||||||
ioWriteOpen(this->write);
|
ioWriteOpen(driver->write);
|
||||||
this->read = ioReadNewP(this, .block = true, .eof = tlsSessionEof, .read = tlsSessionRead);
|
driver->read = ioReadNewP(driver, .block = true, .eof = tlsSessionEof, .read = tlsSessionRead);
|
||||||
ioReadOpen(this->read);
|
ioReadOpen(driver->read);
|
||||||
|
|
||||||
|
// Create session interface
|
||||||
|
this = ioSessionNew(driver, &tlsSessionInterface);
|
||||||
}
|
}
|
||||||
MEM_CONTEXT_NEW_END();
|
MEM_CONTEXT_NEW_END();
|
||||||
|
|
||||||
FUNCTION_LOG_RETURN(TLS_SESSION, this);
|
FUNCTION_LOG_RETURN(IO_SESSION, this);
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
TLS Session
|
TLS Session
|
||||||
|
|
||||||
TLS sessions are created by calling tlsClientOpen().
|
TLS sessions are created by calling ioClientOpen().
|
||||||
|
|
||||||
TLS sessions are generally reused so the user must be prepared to retry their transaction on a read/write error if the server closes
|
TLS sessions are generally reused so the user must be prepared to retry their transaction on a read/write error if the server closes
|
||||||
the session before it is reused. If this behavior is not desirable then tlsSessionFree()/tlsClientOpen() can be called to get a new
|
the session before it is reused. If this behavior is not desirable then ioSessionFree()/ioClientOpen() can be called to get a new
|
||||||
session.
|
session.
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
#ifndef COMMON_IO_TLS_SESSION_H
|
#ifndef COMMON_IO_TLS_SESSION_H
|
||||||
@ -13,45 +13,16 @@ session.
|
|||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
Object type
|
Object type
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
#define TLS_SESSION_TYPE TlsSession
|
#include <openssl/ssl.h>
|
||||||
#define TLS_SESSION_PREFIX tlsSession
|
|
||||||
|
|
||||||
typedef struct TlsSession TlsSession;
|
#include "common/io/session.h"
|
||||||
|
|
||||||
#include "common/io/read.h"
|
|
||||||
#include "common/io/socket/session.h"
|
#include "common/io/socket/session.h"
|
||||||
#include "common/io/write.h"
|
#include "common/time.h"
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
Functions
|
Constructors
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
// Close the session. Shutdown should not be attempted after an error, which means the client never has the oppottunity to do a
|
// Only called by TLS client/server code
|
||||||
// shutdown since the connection is held open until it is disconnected by the server.
|
IoSession *tlsSessionNew(SSL *session, SocketSession *socketSession, TimeMSec timeout);
|
||||||
void tlsSessionClose(TlsSession *this, bool shutdown);
|
|
||||||
|
|
||||||
// Move to a new parent mem context
|
|
||||||
TlsSession *tlsSessionMove(TlsSession *this, MemContext *parentNew);
|
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
|
||||||
Getters/Setters
|
|
||||||
***********************************************************************************************************************************/
|
|
||||||
// Read interface
|
|
||||||
IoRead *tlsSessionIoRead(TlsSession *this);
|
|
||||||
|
|
||||||
// Write interface
|
|
||||||
IoWrite *tlsSessionIoWrite(TlsSession *this);
|
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
|
||||||
Destructor
|
|
||||||
***********************************************************************************************************************************/
|
|
||||||
void tlsSessionFree(TlsSession *this);
|
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
|
||||||
Macros for function logging
|
|
||||||
***********************************************************************************************************************************/
|
|
||||||
#define FUNCTION_LOG_TLS_SESSION_TYPE \
|
|
||||||
TlsSession *
|
|
||||||
#define FUNCTION_LOG_TLS_SESSION_FORMAT(value, buffer, bufferSize) \
|
|
||||||
objToLog(value, "TlsSession", buffer, bufferSize)
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,17 +0,0 @@
|
|||||||
/***********************************************************************************************************************************
|
|
||||||
TLS Session Internal
|
|
||||||
***********************************************************************************************************************************/
|
|
||||||
#ifndef COMMON_IO_TLS_SESSION_INTERN_H
|
|
||||||
#define COMMON_IO_TLS_SESSION_INTERN_H
|
|
||||||
|
|
||||||
#include <openssl/ssl.h>
|
|
||||||
|
|
||||||
#include "common/io/tls/session.h"
|
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
|
||||||
Constructors
|
|
||||||
***********************************************************************************************************************************/
|
|
||||||
// Only called by TLS client/server code
|
|
||||||
TlsSession *tlsSessionNew(SSL *session, SocketSession *socketSession, TimeMSec timeout);
|
|
||||||
|
|
||||||
#endif
|
|
@ -11,6 +11,7 @@ Azure Storage
|
|||||||
#include "common/debug.h"
|
#include "common/debug.h"
|
||||||
#include "common/io/http/client.h"
|
#include "common/io/http/client.h"
|
||||||
#include "common/io/http/common.h"
|
#include "common/io/http/common.h"
|
||||||
|
#include "common/io/tls/client.h"
|
||||||
#include "common/log.h"
|
#include "common/log.h"
|
||||||
#include "common/memContext.h"
|
#include "common/memContext.h"
|
||||||
#include "common/regExp.h"
|
#include "common/regExp.h"
|
||||||
@ -739,7 +740,8 @@ storageAzureNew(
|
|||||||
driver->sasKey = httpQueryNewStr(key);
|
driver->sasKey = httpQueryNewStr(key);
|
||||||
|
|
||||||
// Create the http client used to service requests
|
// Create the http client used to service requests
|
||||||
driver->httpClient = httpClientNew(driver->host, port, timeout, verifyPeer, caFile, caPath);
|
driver->httpClient = httpClientNew(
|
||||||
|
tlsClientNew(sckClientNew(driver->host, port, timeout), timeout, verifyPeer, caFile, caPath), timeout);
|
||||||
|
|
||||||
// Create list of redacted headers
|
// Create list of redacted headers
|
||||||
driver->headerRedactList = strLstNew();
|
driver->headerRedactList = strLstNew();
|
||||||
|
@ -10,6 +10,7 @@ S3 Storage
|
|||||||
#include "common/debug.h"
|
#include "common/debug.h"
|
||||||
#include "common/io/http/client.h"
|
#include "common/io/http/client.h"
|
||||||
#include "common/io/http/common.h"
|
#include "common/io/http/common.h"
|
||||||
|
#include "common/io/tls/client.h"
|
||||||
#include "common/log.h"
|
#include "common/log.h"
|
||||||
#include "common/memContext.h"
|
#include "common/memContext.h"
|
||||||
#include "common/regExp.h"
|
#include "common/regExp.h"
|
||||||
@ -851,7 +852,10 @@ storageS3New(
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Create the HTTP client used to service requests
|
// Create the HTTP client used to service requests
|
||||||
driver->httpClient = httpClientNew(host == NULL ? driver->bucketEndpoint : host, port, timeout, verifyPeer, caFile, caPath);
|
driver->httpClient = httpClientNew(
|
||||||
|
tlsClientNew(
|
||||||
|
sckClientNew(host == NULL ? driver->bucketEndpoint : host, port, timeout), timeout, verifyPeer, caFile, caPath),
|
||||||
|
timeout);
|
||||||
|
|
||||||
// Create list of redacted headers
|
// Create list of redacted headers
|
||||||
driver->headerRedactList = strLstNew();
|
driver->headerRedactList = strLstNew();
|
||||||
|
@ -915,10 +915,6 @@ src/common/io/tls/session.h:
|
|||||||
class: core
|
class: core
|
||||||
type: c/h
|
type: c/h
|
||||||
|
|
||||||
src/common/io/tls/session.intern.h:
|
|
||||||
class: core
|
|
||||||
type: c/h
|
|
||||||
|
|
||||||
src/common/io/write.c:
|
src/common/io/write.c:
|
||||||
class: core
|
class: core
|
||||||
type: c
|
type: c
|
||||||
|
@ -242,6 +242,8 @@ unit:
|
|||||||
total: 5
|
total: 5
|
||||||
|
|
||||||
coverage:
|
coverage:
|
||||||
|
common/io/client: full
|
||||||
|
common/io/session: full
|
||||||
common/io/tls/client: full
|
common/io/tls/client: full
|
||||||
common/io/tls/session: full
|
common/io/tls/session: full
|
||||||
common/io/socket/client: full
|
common/io/socket/client: full
|
||||||
|
@ -12,7 +12,7 @@ TLS Test Harness
|
|||||||
#include "common/crypto/common.h"
|
#include "common/crypto/common.h"
|
||||||
#include "common/error.h"
|
#include "common/error.h"
|
||||||
#include "common/io/socket/session.h"
|
#include "common/io/socket/session.h"
|
||||||
#include "common/io/tls/session.intern.h"
|
#include "common/io/tls/session.h"
|
||||||
#include "common/log.h"
|
#include "common/log.h"
|
||||||
#include "common/type/buffer.h"
|
#include "common/type/buffer.h"
|
||||||
#include "common/type/json.h"
|
#include "common/type/json.h"
|
||||||
@ -271,7 +271,7 @@ void hrnTlsServerRunParam(IoRead *read, const String *certificate, const String
|
|||||||
THROW_SYS_ERROR(AssertError, "unable to listen on socket");
|
THROW_SYS_ERROR(AssertError, "unable to listen on socket");
|
||||||
|
|
||||||
// Loop until no more commands
|
// Loop until no more commands
|
||||||
TlsSession *serverSession = NULL;
|
IoSession *serverSession = NULL;
|
||||||
bool done = false;
|
bool done = false;
|
||||||
|
|
||||||
do
|
do
|
||||||
@ -283,8 +283,7 @@ void hrnTlsServerRunParam(IoRead *read, const String *certificate, const String
|
|||||||
{
|
{
|
||||||
case hrnTlsCmdAbort:
|
case hrnTlsCmdAbort:
|
||||||
{
|
{
|
||||||
tlsSessionClose(serverSession, false);
|
ioSessionFree(serverSession);
|
||||||
tlsSessionFree(serverSession);
|
|
||||||
serverSession = NULL;
|
serverSession = NULL;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -313,8 +312,8 @@ void hrnTlsServerRunParam(IoRead *read, const String *certificate, const String
|
|||||||
if (serverSession == NULL)
|
if (serverSession == NULL)
|
||||||
THROW(AssertError, "TLS session is already closed");
|
THROW(AssertError, "TLS session is already closed");
|
||||||
|
|
||||||
tlsSessionClose(serverSession, true);
|
ioSessionClose(serverSession);
|
||||||
tlsSessionFree(serverSession);
|
ioSessionFree(serverSession);
|
||||||
serverSession = NULL;
|
serverSession = NULL;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -332,7 +331,7 @@ void hrnTlsServerRunParam(IoRead *read, const String *certificate, const String
|
|||||||
const String *expected = varStr(data);
|
const String *expected = varStr(data);
|
||||||
Buffer *buffer = bufNew(strSize(expected));
|
Buffer *buffer = bufNew(strSize(expected));
|
||||||
|
|
||||||
ioRead(tlsSessionIoRead(serverSession), buffer);
|
ioRead(ioSessionIoRead(serverSession), buffer);
|
||||||
|
|
||||||
// Treat any ? characters as wildcards so variable elements (e.g. auth hashes) can be ignored
|
// Treat any ? characters as wildcards so variable elements (e.g. auth hashes) can be ignored
|
||||||
String *actual = strNewBuf(buffer);
|
String *actual = strNewBuf(buffer);
|
||||||
@ -352,8 +351,8 @@ void hrnTlsServerRunParam(IoRead *read, const String *certificate, const String
|
|||||||
|
|
||||||
case hrnTlsCmdReply:
|
case hrnTlsCmdReply:
|
||||||
{
|
{
|
||||||
ioWrite(tlsSessionIoWrite(serverSession), BUFSTR(varStr(data)));
|
ioWrite(ioSessionIoWrite(serverSession), BUFSTR(varStr(data)));
|
||||||
ioWriteFlush(tlsSessionIoWrite(serverSession));
|
ioWriteFlush(ioSessionIoWrite(serverSession));
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -121,7 +121,7 @@ testRun(void)
|
|||||||
|
|
||||||
cfgOptionSet(cfgOptLogTimestamp, cfgSourceParam, varNewBool(true));
|
cfgOptionSet(cfgOptLogTimestamp, cfgSourceParam, varNewBool(true));
|
||||||
|
|
||||||
httpClientNew(strNew("BOGUS"), 443, 1000, true, NULL, NULL);
|
httpClientNew(tlsClientNew(sckClientNew(STRDEF("BOGUS"), 443, 1000), 1000, true, NULL, NULL), 1000);
|
||||||
|
|
||||||
harnessLogLevelSet(logLevelDetail);
|
harnessLogLevelSet(logLevelDetail);
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ Test HTTP
|
|||||||
|
|
||||||
#include "common/io/fdRead.h"
|
#include "common/io/fdRead.h"
|
||||||
#include "common/io/fdWrite.h"
|
#include "common/io/fdWrite.h"
|
||||||
|
#include "common/io/tls/client.h"
|
||||||
|
|
||||||
#include "common/harnessFork.h"
|
#include "common/harnessFork.h"
|
||||||
#include "common/harnessTls.h"
|
#include "common/harnessTls.h"
|
||||||
@ -176,7 +177,9 @@ testRun(void)
|
|||||||
TEST_RESULT_STR(httpClientStatStr(), NULL, "no stats yet");
|
TEST_RESULT_STR(httpClientStatStr(), NULL, "no stats yet");
|
||||||
|
|
||||||
TEST_ASSIGN(
|
TEST_ASSIGN(
|
||||||
client, httpClientNew(strNew("localhost"), hrnTlsServerPort(), 500, testContainer(), NULL, NULL),
|
client,
|
||||||
|
httpClientNew(
|
||||||
|
tlsClientNew(sckClientNew(strNew("localhost"), hrnTlsServerPort(), 500), 500, testContainer(), NULL, NULL), 500),
|
||||||
"new client");
|
"new client");
|
||||||
|
|
||||||
TEST_ERROR_FMT(
|
TEST_ERROR_FMT(
|
||||||
@ -204,7 +207,10 @@ testRun(void)
|
|||||||
ioBufferSizeSet(35);
|
ioBufferSizeSet(35);
|
||||||
|
|
||||||
TEST_ASSIGN(
|
TEST_ASSIGN(
|
||||||
client, httpClientNew(hrnTlsServerHost(), hrnTlsServerPort(), 5000, testContainer(), NULL, NULL),
|
client,
|
||||||
|
httpClientNew(
|
||||||
|
tlsClientNew(sckClientNew(hrnTlsServerHost(), hrnTlsServerPort(), 5000), 5000, testContainer(), NULL, NULL),
|
||||||
|
5000),
|
||||||
"new client");
|
"new client");
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------------------------------------------
|
||||||
|
@ -211,7 +211,7 @@ testRun(void)
|
|||||||
// *****************************************************************************************************************************
|
// *****************************************************************************************************************************
|
||||||
if (testBegin("TlsClient verification"))
|
if (testBegin("TlsClient verification"))
|
||||||
{
|
{
|
||||||
TlsClient *client = NULL;
|
IoClient *client = NULL;
|
||||||
|
|
||||||
// Connection errors
|
// Connection errors
|
||||||
// -------------------------------------------------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------------------------------------------------
|
||||||
@ -219,20 +219,20 @@ testRun(void)
|
|||||||
client, tlsClientNew(sckClientNew(strNew("99.99.99.99.99"), hrnTlsServerPort(), 0), 0, true, NULL, NULL),
|
client, tlsClientNew(sckClientNew(strNew("99.99.99.99.99"), hrnTlsServerPort(), 0), 0, true, NULL, NULL),
|
||||||
"new client");
|
"new client");
|
||||||
TEST_ERROR(
|
TEST_ERROR(
|
||||||
tlsClientOpen(client), HostConnectError, "unable to get address for '99.99.99.99.99': [-2] Name or service not known");
|
ioClientOpen(client), HostConnectError, "unable to get address for '99.99.99.99.99': [-2] Name or service not known");
|
||||||
|
|
||||||
TEST_ASSIGN(
|
TEST_ASSIGN(
|
||||||
client, tlsClientNew(sckClientNew(strNew("localhost"), hrnTlsServerPort(), 100), 100, true, NULL, NULL),
|
client, tlsClientNew(sckClientNew(strNew("localhost"), hrnTlsServerPort(), 100), 100, true, NULL, NULL),
|
||||||
"new client");
|
"new client");
|
||||||
TEST_ERROR_FMT(
|
TEST_ERROR_FMT(
|
||||||
tlsClientOpen(client), HostConnectError, "unable to connect to 'localhost:%u': [111] Connection refused",
|
ioClientOpen(client), HostConnectError, "unable to connect to 'localhost:%u': [111] Connection refused",
|
||||||
hrnTlsServerPort());
|
hrnTlsServerPort());
|
||||||
|
|
||||||
// -------------------------------------------------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------------------------------------------------
|
||||||
TEST_TITLE("bogus client cert/path");
|
TEST_TITLE("bogus client cert/path");
|
||||||
|
|
||||||
TEST_ERROR(
|
TEST_ERROR(
|
||||||
tlsClientOpen(
|
ioClientOpen(
|
||||||
tlsClientNew(
|
tlsClientNew(
|
||||||
sckClientNew(strNew("localhost"), hrnTlsServerPort(), 5000), 0, true, strNew("bogus.crt"), strNew("/bogus"))),
|
sckClientNew(strNew("localhost"), hrnTlsServerPort(), 5000), 0, true, strNew("bogus.crt"), strNew("/bogus"))),
|
||||||
CryptoError, "unable to set user-defined CA certificate location: [33558530] No such file or directory");
|
CryptoError, "unable to set user-defined CA certificate location: [33558530] No such file or directory");
|
||||||
@ -273,7 +273,7 @@ testRun(void)
|
|||||||
hrnTlsServerClose();
|
hrnTlsServerClose();
|
||||||
|
|
||||||
TEST_ERROR_FMT(
|
TEST_ERROR_FMT(
|
||||||
tlsClientOpen(
|
ioClientOpen(
|
||||||
tlsClientNew(
|
tlsClientNew(
|
||||||
sckClientNew(strNew("localhost"), hrnTlsServerPort(), 5000), 0, true, NULL, strNew("/bogus"))),
|
sckClientNew(strNew("localhost"), hrnTlsServerPort(), 5000), 0, true, NULL, strNew("/bogus"))),
|
||||||
CryptoError,
|
CryptoError,
|
||||||
@ -287,7 +287,7 @@ testRun(void)
|
|||||||
hrnTlsServerClose();
|
hrnTlsServerClose();
|
||||||
|
|
||||||
TEST_RESULT_VOID(
|
TEST_RESULT_VOID(
|
||||||
tlsClientOpen(
|
ioClientOpen(
|
||||||
tlsClientNew(
|
tlsClientNew(
|
||||||
sckClientNew(strNew("test.pgbackrest.org"), hrnTlsServerPort(), 5000), 0, true,
|
sckClientNew(strNew("test.pgbackrest.org"), hrnTlsServerPort(), 5000), 0, true,
|
||||||
strNewFmt("%s/" TEST_CERTIFICATE_PREFIX "-ca.crt", testRepoPath()), NULL)),
|
strNewFmt("%s/" TEST_CERTIFICATE_PREFIX "-ca.crt", testRepoPath()), NULL)),
|
||||||
@ -300,7 +300,7 @@ testRun(void)
|
|||||||
hrnTlsServerClose();
|
hrnTlsServerClose();
|
||||||
|
|
||||||
TEST_RESULT_VOID(
|
TEST_RESULT_VOID(
|
||||||
tlsClientOpen(
|
ioClientOpen(
|
||||||
tlsClientNew(
|
tlsClientNew(
|
||||||
sckClientNew(strNew("host.test2.pgbackrest.org"), hrnTlsServerPort(), 5000), 0, true,
|
sckClientNew(strNew("host.test2.pgbackrest.org"), hrnTlsServerPort(), 5000), 0, true,
|
||||||
strNewFmt("%s/" TEST_CERTIFICATE_PREFIX "-ca.crt", testRepoPath()), NULL)),
|
strNewFmt("%s/" TEST_CERTIFICATE_PREFIX "-ca.crt", testRepoPath()), NULL)),
|
||||||
@ -313,7 +313,7 @@ testRun(void)
|
|||||||
hrnTlsServerClose();
|
hrnTlsServerClose();
|
||||||
|
|
||||||
TEST_ERROR(
|
TEST_ERROR(
|
||||||
tlsClientOpen(
|
ioClientOpen(
|
||||||
tlsClientNew(
|
tlsClientNew(
|
||||||
sckClientNew(strNew("test3.pgbackrest.org"), hrnTlsServerPort(), 5000), 0, true,
|
sckClientNew(strNew("test3.pgbackrest.org"), hrnTlsServerPort(), 5000), 0, true,
|
||||||
strNewFmt("%s/" TEST_CERTIFICATE_PREFIX "-ca.crt", testRepoPath()), NULL)),
|
strNewFmt("%s/" TEST_CERTIFICATE_PREFIX "-ca.crt", testRepoPath()), NULL)),
|
||||||
@ -327,7 +327,7 @@ testRun(void)
|
|||||||
hrnTlsServerClose();
|
hrnTlsServerClose();
|
||||||
|
|
||||||
TEST_ERROR_FMT(
|
TEST_ERROR_FMT(
|
||||||
tlsClientOpen(
|
ioClientOpen(
|
||||||
tlsClientNew(
|
tlsClientNew(
|
||||||
sckClientNew(strNew("localhost"), hrnTlsServerPort(), 5000), 0, true,
|
sckClientNew(strNew("localhost"), hrnTlsServerPort(), 5000), 0, true,
|
||||||
strNewFmt("%s/" TEST_CERTIFICATE_PREFIX ".crt", testRepoPath()),
|
strNewFmt("%s/" TEST_CERTIFICATE_PREFIX ".crt", testRepoPath()),
|
||||||
@ -343,7 +343,7 @@ testRun(void)
|
|||||||
hrnTlsServerClose();
|
hrnTlsServerClose();
|
||||||
|
|
||||||
TEST_RESULT_VOID(
|
TEST_RESULT_VOID(
|
||||||
tlsClientOpen(
|
ioClientOpen(
|
||||||
tlsClientNew(sckClientNew(strNew("localhost"), hrnTlsServerPort(), 5000), 0, false, NULL, NULL)),
|
tlsClientNew(sckClientNew(strNew("localhost"), hrnTlsServerPort(), 5000), 0, false, NULL, NULL)),
|
||||||
"open connection");
|
"open connection");
|
||||||
|
|
||||||
@ -359,8 +359,8 @@ testRun(void)
|
|||||||
// *****************************************************************************************************************************
|
// *****************************************************************************************************************************
|
||||||
if (testBegin("TlsClient general usage"))
|
if (testBegin("TlsClient general usage"))
|
||||||
{
|
{
|
||||||
TlsClient *client = NULL;
|
IoClient *client = NULL;
|
||||||
TlsSession *session = NULL;
|
IoSession *session = NULL;
|
||||||
|
|
||||||
// Reset statistics
|
// Reset statistics
|
||||||
sckClientStatLocal = (SocketClientStat){0};
|
sckClientStatLocal = (SocketClientStat){0};
|
||||||
@ -389,7 +389,8 @@ testRun(void)
|
|||||||
|
|
||||||
hrnTlsServerAccept();
|
hrnTlsServerAccept();
|
||||||
|
|
||||||
TEST_ASSIGN(session, tlsClientOpen(client), "open client");
|
TEST_ASSIGN(session, ioClientOpen(client), "open client");
|
||||||
|
TlsSession *tlsSession = (TlsSession *)session->driver;
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------------------------------------------
|
||||||
TEST_TITLE("socket read/write ready");
|
TEST_TITLE("socket read/write ready");
|
||||||
@ -406,22 +407,22 @@ testRun(void)
|
|||||||
TEST_ERROR(
|
TEST_ERROR(
|
||||||
sckReadyRetry(-1, EINVAL, true, &timeout, 0), KernelError, "unable to poll socket: [22] Invalid argument");
|
sckReadyRetry(-1, EINVAL, true, &timeout, 0), KernelError, "unable to poll socket: [22] Invalid argument");
|
||||||
|
|
||||||
TEST_RESULT_BOOL(sckReadyRead(session->socketSession->fd, 0), false, "socket is not read ready");
|
TEST_RESULT_BOOL(sckReadyRead(tlsSession->socketSession->fd, 0), false, "socket is not read ready");
|
||||||
TEST_RESULT_BOOL(sckReadyWrite(session->socketSession->fd, 100), true, "socket is write ready");
|
TEST_RESULT_BOOL(sckReadyWrite(tlsSession->socketSession->fd, 100), true, "socket is write ready");
|
||||||
TEST_RESULT_VOID(sckSessionReadyWrite(session->socketSession), "socket session is write ready");
|
TEST_RESULT_VOID(sckSessionReadyWrite(tlsSession->socketSession), "socket session is write ready");
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------------------------------------------
|
||||||
TEST_TITLE("uncovered errors");
|
TEST_TITLE("uncovered errors");
|
||||||
|
|
||||||
TEST_RESULT_INT(tlsSessionResultProcess(session, SSL_ERROR_WANT_WRITE, 0, 0, false), 0, "write ready");
|
TEST_RESULT_INT(tlsSessionResultProcess(tlsSession, SSL_ERROR_WANT_WRITE, 0, 0, false), 0, "write ready");
|
||||||
TEST_ERROR(
|
TEST_ERROR(
|
||||||
tlsSessionResultProcess(session, SSL_ERROR_WANT_X509_LOOKUP, 336031996, 0, false), ServiceError,
|
tlsSessionResultProcess(tlsSession, SSL_ERROR_WANT_X509_LOOKUP, 336031996, 0, false), ServiceError,
|
||||||
"TLS error [4:336031996] unknown protocol");
|
"TLS error [4:336031996] unknown protocol");
|
||||||
TEST_ERROR(
|
TEST_ERROR(
|
||||||
tlsSessionResultProcess(session, SSL_ERROR_WANT_X509_LOOKUP, 0, 0, false), ServiceError,
|
tlsSessionResultProcess(tlsSession, SSL_ERROR_WANT_X509_LOOKUP, 0, 0, false), ServiceError,
|
||||||
"TLS error [4:0] no details available");
|
"TLS error [4:0] no details available");
|
||||||
TEST_ERROR(
|
TEST_ERROR(
|
||||||
tlsSessionResultProcess(session, SSL_ERROR_ZERO_RETURN, 0, 0, false), ProtocolError, "unexpected TLS eof");
|
tlsSessionResultProcess(tlsSession, SSL_ERROR_ZERO_RETURN, 0, 0, false), ProtocolError, "unexpected TLS eof");
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------------------------------------------
|
||||||
TEST_TITLE("first protocol exchange");
|
TEST_TITLE("first protocol exchange");
|
||||||
@ -430,11 +431,11 @@ testRun(void)
|
|||||||
hrnTlsServerReplyZ("something:0\n");
|
hrnTlsServerReplyZ("something:0\n");
|
||||||
|
|
||||||
const Buffer *input = BUFSTRDEF("some protocol info");
|
const Buffer *input = BUFSTRDEF("some protocol info");
|
||||||
TEST_RESULT_VOID(ioWrite(tlsSessionIoWrite(session), input), "write input");
|
TEST_RESULT_VOID(ioWrite(ioSessionIoWrite(session), input), "write input");
|
||||||
ioWriteFlush(tlsSessionIoWrite(session));
|
ioWriteFlush(ioSessionIoWrite(session));
|
||||||
|
|
||||||
TEST_RESULT_STR_Z(ioReadLine(tlsSessionIoRead(session)), "something:0", "read line");
|
TEST_RESULT_STR_Z(ioReadLine(ioSessionIoRead(session)), "something:0", "read line");
|
||||||
TEST_RESULT_BOOL(ioReadEof(tlsSessionIoRead(session)), false, "check eof = false");
|
TEST_RESULT_BOOL(ioReadEof(ioSessionIoRead(session)), false, "check eof = false");
|
||||||
|
|
||||||
hrnTlsServerSleep(100);
|
hrnTlsServerSleep(100);
|
||||||
hrnTlsServerReplyZ("some ");
|
hrnTlsServerReplyZ("some ");
|
||||||
@ -443,14 +444,14 @@ testRun(void)
|
|||||||
hrnTlsServerReplyZ("contentAND MORE");
|
hrnTlsServerReplyZ("contentAND MORE");
|
||||||
|
|
||||||
Buffer *output = bufNew(12);
|
Buffer *output = bufNew(12);
|
||||||
TEST_RESULT_UINT(ioRead(tlsSessionIoRead(session), output), 12, "read output");
|
TEST_RESULT_UINT(ioRead(ioSessionIoRead(session), output), 12, "read output");
|
||||||
TEST_RESULT_STR_Z(strNewBuf(output), "some content", "check output");
|
TEST_RESULT_STR_Z(strNewBuf(output), "some content", "check output");
|
||||||
TEST_RESULT_BOOL(ioReadEof(tlsSessionIoRead(session)), false, "check eof = false");
|
TEST_RESULT_BOOL(ioReadEof(ioSessionIoRead(session)), false, "check eof = false");
|
||||||
|
|
||||||
output = bufNew(8);
|
output = bufNew(8);
|
||||||
TEST_RESULT_UINT(ioRead(tlsSessionIoRead(session), output), 8, "read output");
|
TEST_RESULT_UINT(ioRead(ioSessionIoRead(session), output), 8, "read output");
|
||||||
TEST_RESULT_STR_Z(strNewBuf(output), "AND MORE", "check output");
|
TEST_RESULT_STR_Z(strNewBuf(output), "AND MORE", "check output");
|
||||||
TEST_RESULT_BOOL(ioReadEof(tlsSessionIoRead(session)), false, "check eof = false");
|
TEST_RESULT_BOOL(ioReadEof(ioSessionIoRead(session)), false, "check eof = false");
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------------------------------------------
|
||||||
TEST_TITLE("read eof");
|
TEST_TITLE("read eof");
|
||||||
@ -458,11 +459,11 @@ testRun(void)
|
|||||||
hrnTlsServerSleep(500);
|
hrnTlsServerSleep(500);
|
||||||
|
|
||||||
output = bufNew(12);
|
output = bufNew(12);
|
||||||
session->socketSession->timeout = 100;
|
tlsSession->socketSession->timeout = 100;
|
||||||
TEST_ERROR_FMT(
|
TEST_ERROR_FMT(
|
||||||
ioRead(tlsSessionIoRead(session), output), ProtocolError,
|
ioRead(ioSessionIoRead(session), output), ProtocolError,
|
||||||
"timeout after 100ms waiting for read from '%s:%u'", strZ(hrnTlsServerHost()), hrnTlsServerPort());
|
"timeout after 100ms waiting for read from '%s:%u'", strZ(hrnTlsServerHost()), hrnTlsServerPort());
|
||||||
session->socketSession->timeout = 5000;
|
tlsSession->socketSession->timeout = 5000;
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------------------------------------------
|
||||||
TEST_TITLE("second protocol exchange");
|
TEST_TITLE("second protocol exchange");
|
||||||
@ -473,19 +474,19 @@ testRun(void)
|
|||||||
hrnTlsServerClose();
|
hrnTlsServerClose();
|
||||||
|
|
||||||
input = BUFSTRDEF("more protocol info");
|
input = BUFSTRDEF("more protocol info");
|
||||||
TEST_RESULT_VOID(ioWrite(tlsSessionIoWrite(session), input), "write input");
|
TEST_RESULT_VOID(ioWrite(ioSessionIoWrite(session), input), "write input");
|
||||||
ioWriteFlush(tlsSessionIoWrite(session));
|
ioWriteFlush(ioSessionIoWrite(session));
|
||||||
|
|
||||||
output = bufNew(12);
|
output = bufNew(12);
|
||||||
TEST_RESULT_UINT(ioRead(tlsSessionIoRead(session), output), 12, "read output");
|
TEST_RESULT_UINT(ioRead(ioSessionIoRead(session), output), 12, "read output");
|
||||||
TEST_RESULT_STR_Z(strNewBuf(output), "0123456789AB", "check output");
|
TEST_RESULT_STR_Z(strNewBuf(output), "0123456789AB", "check output");
|
||||||
TEST_RESULT_BOOL(ioReadEof(tlsSessionIoRead(session)), false, "check eof = false");
|
TEST_RESULT_BOOL(ioReadEof(ioSessionIoRead(session)), false, "check eof = false");
|
||||||
|
|
||||||
output = bufNew(12);
|
output = bufNew(12);
|
||||||
TEST_RESULT_UINT(ioRead(tlsSessionIoRead(session), output), 0, "read no output after eof");
|
TEST_RESULT_UINT(ioRead(ioSessionIoRead(session), output), 0, "read no output after eof");
|
||||||
TEST_RESULT_BOOL(ioReadEof(tlsSessionIoRead(session)), true, "check eof = true");
|
TEST_RESULT_BOOL(ioReadEof(ioSessionIoRead(session)), true, "check eof = true");
|
||||||
|
|
||||||
TEST_RESULT_VOID(tlsSessionClose(session, false), "close again");
|
TEST_RESULT_VOID(ioSessionClose(session), "close again");
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------------------------------------------
|
||||||
TEST_TITLE("aborted connection before read complete (blocking socket)");
|
TEST_TITLE("aborted connection before read complete (blocking socket)");
|
||||||
@ -495,16 +496,16 @@ testRun(void)
|
|||||||
hrnTlsServerAbort();
|
hrnTlsServerAbort();
|
||||||
|
|
||||||
socketLocal.block = true;
|
socketLocal.block = true;
|
||||||
TEST_ASSIGN(session, tlsClientOpen(client), "open client again (was closed by server)");
|
TEST_ASSIGN(session, ioClientOpen(client), "open client again (was closed by server)");
|
||||||
socketLocal.block = false;
|
socketLocal.block = false;
|
||||||
|
|
||||||
output = bufNew(13);
|
output = bufNew(13);
|
||||||
TEST_ERROR(ioRead(tlsSessionIoRead(session), output), KernelError, "TLS syscall error");
|
TEST_ERROR(ioRead(ioSessionIoRead(session), output), KernelError, "TLS syscall error");
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------------------------------------------
|
||||||
TEST_TITLE("close connection");
|
TEST_TITLE("close connection");
|
||||||
|
|
||||||
TEST_RESULT_VOID(tlsClientFree(client), "free client");
|
TEST_RESULT_VOID(ioClientFree(client), "free client");
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------------------------------------------
|
||||||
hrnTlsClientEnd();
|
hrnTlsClientEnd();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user