1
0
Fork 0

Merge branch 'devel' of ssh://github.com/arangodb/arangodb into devel

This commit is contained in:
Max Neunhoeffer 2015-01-30 15:25:16 +01:00
commit 600cef8ec4
12 changed files with 2702 additions and 72 deletions

View File

@ -1,3 +1,18 @@
branches:
only:
- master
- 1.0
- 1.1
- 1.2
- 1.3
- 1.4
- 2.0
- 2.1
- 2.2
- 2.3
- 2.4
- devel
language: cpp
compiler: g++
@ -27,20 +42,8 @@ install:
- sudo apt-get -y install gdb
before_script: "bash -c Installation/travisCI/before_script.sh"
script: "bash -c Installation/travisCI/script.sh"
script:
- "bash -c Installation/travisCI/build.sh"
- "bash -c Installation/travisCI/jslint.sh"
- "bash -c Installation/travisCI/tests.sh"
after_failure: "bash -c Installation/travisCI/after_failure.sh"
branches:
only:
- master
- 1.0
- 1.1
- 1.2
- 1.3
- 1.4
- 2.0
- 2.1
- 2.2
- 2.3
- 2.4
- devel

View File

@ -29,10 +29,18 @@ v2.5.0 (XXXX-XX-XX)
v2.4.2 (2015-XX-XX)
-------------------
* added custom visitor functionality for AQL traversals
This allows more complex result processing in traversals triggered by AQL. A few examples
are shown in [this article](http://jsteemann.github.io/blog/2015/01/28/using-custom-visitors-in-aql-graph-traversals/).
* improved number of results estimated for nodes of type EnumerateListNode and SubqueryNode
in AQL explain output
* added AQL explain helper:
* added AQL explain helper to explain arbitrary AQL queries
The helper function prints the query execution plan and the indexes to be used in the
query. It can be invoked from the ArangoShell or the web interface as follows:
require("org/arangodb/aql/explainer").explain(query);

View File

@ -18,8 +18,6 @@ following attribute naming constraints are not violated:
end users should try to avoid using their own attribute names starting with
underscores.
* Attribute names should not start with the at-mark (*@*). The at-mark
at the start of attribute names is reserved in ArangoDB for future use cases.
* Theoretically, attribute names can include punctuation and special characters
as desired, provided the name is a valid UTF-8 string. For maximum
portability, special characters should be avoided though. For example,
@ -30,6 +28,10 @@ following attribute naming constraints are not violated:
attribute names which don't require any quoting/escaping in all languages
used. This includes languages used by the client (e.g. Ruby, PHP) if the
attributes are mapped to object members there.
* Attribute names starting with an at-mark (*@*) will need to be enclosed in
backticks when used in an AQL query to tell them apart from bind variables.
Therefore we do not encourage the use of attributes starting with at-marks,
though they will work when used properly.
* ArangoDB does not enforce a length limit for attribute names. However, long
attribute names may use more memory in result sets etc. Therefore the use
of long attribute names is discouraged.

View File

@ -436,9 +436,9 @@ SHELL_COMMON = \
@top_srcdir@/js/common/tests/shell-errors.js \
@top_srcdir@/js/common/tests/shell-fs.js \
@top_srcdir@/js/common/tests/shell-general-graph.js \
@top_srcdir@/js/common/tests/shell-graph-traversal.js \
@top_srcdir@/js/common/tests/shell-graph-algorithms.js \
@top_srcdir@/js/common/tests/shell-graph-measurement.js \
@top_srcdir@/js/common/tests/shell-graph-traversal.js \
@top_srcdir@/js/common/tests/shell-keygen.js \
@top_srcdir@/js/common/tests/shell-keygen-noncluster.js \
@top_srcdir@/js/common/tests/shell-index-ensure.js \
@ -553,6 +553,7 @@ SHELL_SERVER_AQL = @top_srcdir@/js/server/tests/aql-arithmetic.js \
@top_srcdir@/js/server/tests/aql-functions-types.js \
@top_srcdir@/js/server/tests/aql-general-graph.js \
@top_srcdir@/js/server/tests/aql-graph.js \
@top_srcdir@/js/server/tests/aql-graph-visitors.js \
@top_srcdir@/js/server/tests/aql-hash-noncluster.js \
@top_srcdir@/js/server/tests/aql-is-in-polygon.js \
@top_srcdir@/js/server/tests/aql-logical.js \

View File

@ -1578,6 +1578,7 @@ void RestReplicationHandler::handleCommandRestoreCollection () {
TRI_Insert3ObjectJson(TRI_CORE_MEM_ZONE, &result, "result", TRI_CreateBooleanJson(TRI_CORE_MEM_ZONE, true));
generateResult(&result);
TRI_DestroyJson(TRI_CORE_MEM_ZONE, &result);
}
}
@ -1624,6 +1625,7 @@ void RestReplicationHandler::handleCommandRestoreIndexes () {
TRI_Insert3ObjectJson(TRI_CORE_MEM_ZONE, &result, "result", TRI_CreateBooleanJson(TRI_CORE_MEM_ZONE, true));
generateResult(&result);
TRI_DestroyJson(TRI_CORE_MEM_ZONE, &result);
}
}
@ -2403,6 +2405,7 @@ void RestReplicationHandler::handleCommandRestoreData () {
TRI_Insert3ObjectJson(TRI_CORE_MEM_ZONE, &result, "result", TRI_CreateBooleanJson(TRI_CORE_MEM_ZONE, true));
generateResult(&result);
TRI_DestroyJson(TRI_CORE_MEM_ZONE, &result);
}
}
@ -2693,6 +2696,7 @@ void RestReplicationHandler::handleCommandRestoreDataCoordinator () {
TRI_Insert3ObjectJson(TRI_CORE_MEM_ZONE, &result, "result", TRI_CreateBooleanJson(TRI_CORE_MEM_ZONE, true));
generateResult(&result);
TRI_DestroyJson(TRI_CORE_MEM_ZONE, &result);
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -367,6 +367,25 @@ function startInstance (protocol, options, addArgs, testname) {
return instanceInfo;
}
function readImportantLogLines(logFilename) {
var importantLines = [];
var buf = fs.readBuffer(logFilename);
var i;
var lineStart = 0;
var maxBuffer = buf.length;
for (i = 0; i < maxBuffer; i++) {
if (buf[i] === 10) { // \n
var line = buf.asciiSlice(lineStart, i - 1);
// filter out regular INFO lines, and test related messages
if ((line.search(" INFO ") < 0) &&
(line.search("WARNING about to execute:") < 0)) {
importantLines.push(line);
}
lineStart = i + 1;
}
}
return importantLines;
}
function copy (src, dst) {
var fs = require("fs");
@ -503,6 +522,8 @@ function shutdownInstance (instanceInfo, options) {
}
}
instanceInfo.importantLogLines = readImportantLogLines(fs.join(instanceInfo.tmpDataDir, "log"));
cleanupDirectories = cleanupDirectories.concat([instanceInfo.tmpDataDir, instanceInfo.flatTmpDataDir]);
}
@ -792,6 +813,9 @@ function performTests(options, testList, testname, remote) {
shutdownInstance(instanceInfo,options);
}
print("done.");
if (instanceInfo.hasOwnProperty('importantLogLines') && instanceInfo.importantLogLines.length > 0) {
print("Found messages in the server logs: \n" + yaml.safeDump(instanceInfo.importantLogLines));
}
return results;
}
@ -828,6 +852,10 @@ testFuncs.single_server = function (options) {
}
shutdownInstance(instanceInfo,options);
print("done.");
if (instanceInfo.hasOwnProperty('importantLogLines') && instanceInfo.importantLogLines.length > 0) {
print("Found messages in the server logs: \n" + yaml.safeDump(instanceInfo.importantLogLines));
}
return result;
}
else {
@ -872,6 +900,9 @@ testFuncs.single_client = function (options) {
}
shutdownInstance(instanceInfo,options);
print("done.");
if (instanceInfo.hasOwnProperty('importantLogLines') && instanceInfo.importantLogLines.length > 0) {
print("Found messages in the server logs: \n" + yaml.safeDump(instanceInfo.importantLogLines));
}
return result;
}
else {
@ -989,6 +1020,9 @@ testFuncs.shell_client = function(options) {
print("Shutting down...");
shutdownInstance(instanceInfo, options);
print("done.");
if (instanceInfo.hasOwnProperty('importantLogLines') && instanceInfo.importantLogLines.length > 0) {
print("Found messages in the server logs: \n" + yaml.safeDump(instanceInfo.importantLogLines));
}
return results;
};
@ -1114,6 +1148,9 @@ function rubyTests (options, ssl) {
fs.remove(tmpname);
shutdownInstance(instanceInfo,options);
print("done.");
if (instanceInfo.hasOwnProperty('importantLogLines') && instanceInfo.importantLogLines.length > 0) {
print("Found messages in the server logs: \n" + yaml.safeDump(instanceInfo.importantLogLines));
}
return result;
}
@ -1256,6 +1293,9 @@ testFuncs.importing = function (options) {
print("Shutting down...");
shutdownInstance(instanceInfo,options);
print("done.");
if (instanceInfo.hasOwnProperty('importantLogLines') && instanceInfo.importantLogLines.length > 0) {
print("Found messages in the server logs: \n" + yaml.safeDump(instanceInfo.importantLogLines));
}
return result;
};
@ -1315,6 +1355,9 @@ testFuncs.foxx_manager = function (options) {
print("Shutting down...");
shutdownInstance(instanceInfo,options);
print("done.");
if (instanceInfo.hasOwnProperty('importantLogLines') && instanceInfo.importantLogLines.length > 0) {
print("Found messages in the server logs: \n" + yaml.safeDump(instanceInfo.importantLogLines));
}
return results;
};
@ -1349,6 +1392,9 @@ testFuncs.dump = function (options) {
print("Shutting down...");
shutdownInstance(instanceInfo,options);
print("done.");
if (instanceInfo.hasOwnProperty('importantLogLines') && instanceInfo.importantLogLines.length > 0) {
print("Found messages in the server logs: \n" + yaml.safeDump(instanceInfo.importantLogLines));
}
return results;
};
@ -1409,6 +1455,9 @@ testFuncs.arangob = function (options) {
print("Shutting down...");
shutdownInstance(instanceInfo,options);
print("done.");
if (instanceInfo.hasOwnProperty('importantLogLines') && instanceInfo.importantLogLines.length > 0) {
print("Found messages in the server logs: \n" + yaml.safeDump(instanceInfo.importantLogLines));
}
return results;
};
@ -1426,6 +1475,9 @@ testFuncs.authentication = function (options) {
print("Shutting down...");
shutdownInstance(instanceInfo,options);
print("done.");
if (instanceInfo.hasOwnProperty('importantLogLines') && instanceInfo.importantLogLines.length > 0) {
print("Found messages in the server logs: \n" + yaml.safeDump(instanceInfo.importantLogLines));
}
return results;
};
@ -1493,6 +1545,9 @@ testFuncs.authentication_parameters = function (options) {
print("Shutting down Full test...");
shutdownInstance(instanceInfo,options);
if (instanceInfo.hasOwnProperty('importantLogLines') && instanceInfo.importantLogLines.length > 0) {
print("Found messages in the server logs: \n" + yaml.safeDump(instanceInfo.importantLogLines));
}
print("done with Full test.");
// Only system authentication:
continueTesting = true;
@ -1533,6 +1588,9 @@ testFuncs.authentication_parameters = function (options) {
print("Shutting down System test...");
shutdownInstance(instanceInfo,options);
if (instanceInfo.hasOwnProperty('importantLogLines') && instanceInfo.importantLogLines.length > 0) {
print("Found messages in the server logs: \n" + yaml.safeDump(instanceInfo.importantLogLines));
}
print("done with System test.");
// No authentication:
instanceInfo = startInstance("tcp", options,
@ -1574,6 +1632,9 @@ testFuncs.authentication_parameters = function (options) {
print("Shutting down None test...");
shutdownInstance(instanceInfo,options);
if (instanceInfo.hasOwnProperty('importantLogLines') && instanceInfo.importantLogLines.length > 0) {
print("Found messages in the server logs: \n" + yaml.safeDump(instanceInfo.importantLogLines));
}
print("done with None test.");
return results;
};

File diff suppressed because it is too large Load Diff

View File

@ -265,6 +265,16 @@ namespace triagens {
virtual std::string getHostString () const = 0;
// -----------------------------------------------------------------------------
// --SECTION-- protected variables
// -----------------------------------------------------------------------------
public:
////////////////////////////////////////////////////////////////////////////////
/// @brief error message if failure occured
////////////////////////////////////////////////////////////////////////////////
std::string _errorMessage;
// -----------------------------------------------------------------------------
// --SECTION-- protected variables
// -----------------------------------------------------------------------------

View File

@ -39,6 +39,23 @@
using namespace triagens::basics;
using namespace triagens::rest;
#ifdef _WIN32
#define STR_ERROR() \
windowsErrorBuf; \
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, \
NULL, \
GetLastError(), \
0, \
windowsErrorBuf, \
sizeof(windowsErrorBuf), NULL); \
errno = GetLastError();
#else
#define STR_ERROR() strerror(errno)
#endif
// -----------------------------------------------------------------------------
// --SECTION-- EndpointIp
// -----------------------------------------------------------------------------
@ -104,6 +121,11 @@ EndpointIp::~EndpointIp () {
TRI_socket_t EndpointIp::connectSocket (const struct addrinfo* aip,
double connectTimeout,
double requestTimeout) {
const char *pErr;
char errBuf[256];
#ifdef _WIN32
char windowsErrorBuf[256];
#endif
// set address and port
char host[NI_MAXHOST];
char serv[NI_MAXSERV];
@ -119,7 +141,13 @@ TRI_socket_t EndpointIp::connectSocket (const struct addrinfo* aip,
listenSocket = TRI_socket(aip->ai_family, aip->ai_socktype, aip->ai_protocol);
if (! TRI_isvalidsocket(listenSocket)) {
LOG_ERROR("socket() failed with %d (%s)", errno, strerror(errno));
pErr = STR_ERROR();
snprintf(errBuf, sizeof(errBuf),
"socket() failed with %d - %s",
errno, pErr);
LOG_ERROR("%s", errBuf);
_errorMessage = errBuf;
return listenSocket;
}
@ -129,7 +157,14 @@ TRI_socket_t EndpointIp::connectSocket (const struct addrinfo* aip,
int excl = 1;
if (TRI_setsockopt(listenSocket, SOL_SOCKET, SO_EXCLUSIVEADDRUSE,
reinterpret_cast<char*> (&excl), sizeof (excl)) == -1) {
LOG_ERROR("setsockopt() failed with %d", WSAGetLastError());
pErr = STR_ERROR();
snprintf(errBuf, sizeof(errBuf), "setsockopt() failed with #%d - %s",
errno,
pErr);
LOG_ERROR("%s", errBuf);
_errorMessage = errBuf;
TRI_CLOSE_SOCKET(listenSocket);
TRI_invalidatesocket(&listenSocket);
@ -140,7 +175,14 @@ TRI_socket_t EndpointIp::connectSocket (const struct addrinfo* aip,
if (_reuseAddress) {
int opt = 1;
if (TRI_setsockopt(listenSocket, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<char*> (&opt), sizeof (opt)) == -1) {
LOG_ERROR("setsockopt() failed with %d (%s)", errno, strerror(errno));
pErr = STR_ERROR();
snprintf(errBuf, sizeof(errBuf), "setsockopt() failed with #%d - %s",
errno,
pErr);
LOG_ERROR("%s", errBuf);
_errorMessage = errBuf;
TRI_CLOSE_SOCKET(listenSocket);
TRI_invalidatesocket(&listenSocket);
@ -153,12 +195,16 @@ TRI_socket_t EndpointIp::connectSocket (const struct addrinfo* aip,
int result = TRI_bind(listenSocket, aip->ai_addr, (int) aip->ai_addrlen);
if (result != 0) {
// error
#ifndef _WIN32
LOG_ERROR("bind(address '%s', port %d) failed with %d (%s)", host, (int) _port, errno, strerror(errno));
#else
LOG_ERROR("bind(address '%s', port %d) failed with %d", host, (int) _port, WSAGetLastError());
#endif
pErr = STR_ERROR();
snprintf(errBuf, sizeof(errBuf), "bind(address '%s', port %d) failed with #%d - %s",
host,
(int) _port,
errno,
pErr);
LOG_ERROR("%s", errBuf);
_errorMessage = errBuf;
TRI_CLOSE_SOCKET(listenSocket);
TRI_invalidatesocket(&listenSocket);
@ -170,8 +216,13 @@ TRI_socket_t EndpointIp::connectSocket (const struct addrinfo* aip,
result = TRI_listen(listenSocket, _listenBacklog);
if (result != 0) {
// todo: get the correct error code using WSAGetLastError for windows
LOG_ERROR("listen() failed with %d (%s)", errno, strerror(errno));
pErr = STR_ERROR();
snprintf(errBuf, sizeof(errBuf),
"listen() failed with #%d - %s",
errno, pErr);
LOG_ERROR("%s", errBuf);
_errorMessage = errBuf;
TRI_CLOSE_SOCKET(listenSocket);
TRI_invalidatesocket(&listenSocket);
@ -187,6 +238,14 @@ TRI_socket_t EndpointIp::connectSocket (const struct addrinfo* aip,
int result = TRI_connect(listenSocket, (const struct sockaddr*) aip->ai_addr, (int) aip->ai_addrlen);
if (result != 0) {
pErr = STR_ERROR();
snprintf(errBuf, sizeof(errBuf),
"connect() failed with #%d - %s",
errno, pErr);
LOG_ERROR("%s", errBuf);
_errorMessage = errBuf;
TRI_CLOSE_SOCKET(listenSocket);
TRI_invalidatesocket(&listenSocket);
return listenSocket;
@ -256,10 +315,12 @@ TRI_socket_t EndpointIp::connect (double connectTimeout,
switch (lastError) {
case WSANOTINITIALISED: {
LOG_ERROR("getaddrinfo for host '%s': WSAStartup was not called or not called successfully.", _host.c_str());
_errorMessage = std::string("getaddrinfo for host '") + _host + std::string("': WSAStartup was not called or not called successfully.");
break;
}
default: {
LOG_ERROR("getaddrinfo for host '%s': %s", _host.c_str(), gai_strerror(error));
_errorMessage = std::string("getaddrinfo for host '") + _host + std::string("': ") + gai_strerror(error);
break;
}
}
@ -313,6 +374,7 @@ TRI_socket_t EndpointIp::connect (double connectTimeout, double requestTimeout)
if (error != 0) {
LOG_ERROR("getaddrinfo for host '%s': %s", _host.c_str(), gai_strerror(error));
_errorMessage = std::string("getaddrinfo for host '") + _host + std::string("': ") + gai_strerror(error);
if (result != 0) {
freeaddrinfo(result);
@ -362,9 +424,19 @@ bool EndpointIp::initIncoming (TRI_socket_t incoming) {
int res = TRI_setsockopt(incoming, IPPROTO_TCP, TCP_NODELAY, (char*) &n, sizeof(n));
if (res != 0 ) {
// todo: get correct windows error code
LOG_WARNING("setsockopt failed with %d (%s)", errno, strerror(errno));
const char *pErr;
char errBuf[256];
#ifdef _WIN32
char windowsErrorBuf[256];
#endif
pErr = STR_ERROR();
snprintf(errBuf, sizeof(errBuf), "setsockopt failed with #%d - %s",
errno,
pErr);
LOG_WARNING("%s", errBuf);
_errorMessage = errBuf;
return false;
}

View File

@ -122,7 +122,7 @@ bool ClientConnection::connectSocket () {
_socket = _endpoint->connect(_connectTimeout, _requestTimeout);
if (! TRI_isvalidsocket(_socket)) {
_errorDetails = std::string("failed to connect : ") + std::string(strerror(errno));
_errorDetails = _endpoint->_errorMessage;
return false;
}

View File

@ -162,10 +162,11 @@ namespace triagens {
&bytesWritten);
if (! res) {
if (TRI_errno() != TRI_ERROR_NO_ERROR) {
setErrorMessage(TRI_last_error(), false);
}
setErrorMessage("Error writing to '" +
_connection->getEndpoint()->getSpecification() +
"' '" +
_connection->getErrorDetails() +
"'");
this->close(); // this sets _state to IN_CONNECT for a retry
}
else {
@ -194,6 +195,11 @@ namespace triagens {
// If there was an error, then we are doomed:
if (! res) {
setErrorMessage("Error reading from: '" +
_connection->getEndpoint()->getSpecification() +
"' '" +
_connection->getErrorDetails() +
"'");
this->close(); // this sets the state to IN_CONNECT for a retry
break;
}
@ -292,7 +298,7 @@ namespace triagens {
_connection->getEndpoint()->getSpecification() +
"' '" +
_connection->getErrorDetails() +
"' '");
"'");
_state = DEAD;
}
else {

View File

@ -51,6 +51,19 @@
#include <openssl/ssl.h>
#ifdef _WIN32
#define STR_ERROR() \
windowsErrorBuf; \
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, \
NULL, \
GetLastError(), \
0, \
windowsErrorBuf, \
sizeof(windowsErrorBuf), NULL); \
errno = GetLastError();
#else
#define STR_ERROR() strerror(errno)
#endif
using namespace triagens::basics;
@ -137,6 +150,11 @@ SslClientConnection::~SslClientConnection () {
////////////////////////////////////////////////////////////////////////////////
bool SslClientConnection::connectSocket () {
const char *pErr;
#ifdef _WIN32
char windowsErrorBuf[256];
#endif
TRI_ASSERT(_endpoint != nullptr);
if (_endpoint->isConnected()) {
@ -146,7 +164,7 @@ bool SslClientConnection::connectSocket () {
_socket = _endpoint->connect(_connectTimeout, _requestTimeout);
if (! TRI_isvalidsocket(_socket) || _ctx == nullptr) {
_errorDetails = std::string("failed to connect : ") + std::string(strerror(errno));
_errorDetails = _endpoint->_errorMessage;
return false;
}
@ -181,38 +199,43 @@ bool SslClientConnection::connectSocket () {
(errorDetail == SSL_ERROR_WANT_WRITE)) {
return true;
}
errorDetail = ERR_get_error(); /* Gets the earliest error code from the
thread's error queue and removes the
entry. */
switch(errorDetail) {
case 0x1407E086:
/* 1407E086:
SSL routines:
SSL2_SET_CERTIFICATE:
certificate verify failed */
/* fall-through */
case 0x14090086:
/* 14090086:
SSL routines:
SSL3_GET_SERVER_CERTIFICATE:
certificate verify failed */
certError = SSL_get_verify_result(_ssl);
if(certError != X509_V_OK) {
_errorDetails = std::string("SSL: certificate problem: ") +
X509_verify_cert_error_string(certError);
}
else {
_errorDetails = std::string("SSL: certificate problem, verify that the CA cert is OK.");
}
break;
default:
char errorBuffer[256];
ERR_error_string_n(errorDetail, errorBuffer, sizeof(errorBuffer));
_errorDetails = std::string("SSL: ") + errorBuffer;
break;
else if (errorDetail == SSL_ERROR_SYSCALL) {
pErr = STR_ERROR();
_errorDetails = std::string("SSL: during SSL_connect: ") + std::to_string(errno) + std::string(" - ") + pErr;
}
else {
errorDetail = ERR_get_error(); /* Gets the earliest error code from the
thread's error queue and removes the
entry. */
switch(errorDetail) {
case 0x1407E086:
/* 1407E086:
SSL routines:
SSL2_SET_CERTIFICATE:
certificate verify failed */
/* fall-through */
case 0x14090086:
/* 14090086:
SSL routines:
SSL3_GET_SERVER_CERTIFICATE:
certificate verify failed */
certError = SSL_get_verify_result(_ssl);
if(certError != X509_V_OK) {
_errorDetails = std::string("SSL: certificate problem: ") +
X509_verify_cert_error_string(certError);
}
else {
_errorDetails = std::string("SSL: certificate problem, verify that the CA cert is OK.");
}
break;
default:
char errorBuffer[256];
ERR_error_string_n(errorDetail, errorBuffer, sizeof(errorBuffer));
_errorDetails = std::string("SSL: ") + errorBuffer;
break;
}
}
_endpoint->disconnect();
SSL_free(_ssl);
_ssl = 0;
@ -278,6 +301,10 @@ bool SslClientConnection::prepare (const double timeout, const bool isWrite) con
////////////////////////////////////////////////////////////////////////////////
bool SslClientConnection::writeClientConnection (void* buffer, size_t length, size_t* bytesWritten) {
const char *pErr;
#ifdef _WIN32
char windowsErrorBuf[256];
#endif
*bytesWritten = 0;
if (_ssl == 0) {
@ -301,8 +328,9 @@ bool SslClientConnection::writeClientConnection (void* buffer, size_t length, si
case SSL_ERROR_WANT_CONNECT:
break;
case SSL_ERROR_SYSCALL:
pErr = STR_ERROR();
_errorDetails = std::string("SSL: while writing: SYSCALL returned errno = ") +
std::to_string(errno) + std::string(" - ") + strerror(errno);
std::to_string(errno) + std::string(" - ") + pErr;
break;
case SSL_ERROR_SSL:
/* A failure in the SSL library occurred, usually a protocol error.
@ -327,6 +355,11 @@ return false;
bool SslClientConnection::readClientConnection (StringBuffer& stringBuffer,
bool& connectionClosed) {
const char *pErr;
#ifdef _WIN32
char windowsErrorBuf[256];
#endif
connectionClosed = true;
if (_ssl == nullptr) {
return false;
@ -367,11 +400,12 @@ again:
case SSL_ERROR_WANT_CONNECT:
case SSL_ERROR_SYSCALL:
default:
pErr = STR_ERROR();
int errorDetail = ERR_get_error();
char errorBuffer[256];
ERR_error_string_n(errorDetail, errorBuffer, sizeof(errorBuffer));
_errorDetails = std::string("SSL: while reading: error '") + std::to_string(errno) +
std::string("' - ") + errorBuffer;
std::string("' - ") + errorBuffer + std::string("' - ") + pErr;
/* unexpected */
connectionClosed = true;