Skip to content

Commit a2a2adc

Browse files
committed
Merge branch 'fix to SSLSocket' into main
2 parents 10bc9af + 90607d9 commit a2a2adc

File tree

8 files changed

+162
-30
lines changed

8 files changed

+162
-30
lines changed

include/comm/Exception.h

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#pragma once
3232

3333
#include <string>
34+
#include <iostream>
3435

3536
namespace comm {
3637

@@ -65,37 +66,50 @@ namespace comm {
6566
// Additional information
6667
const std::string msg;
6768
const int errno_val;
69+
const int ssl_err_code;
6870

6971
// Where it was thrown
7072
const char * const file; // Source file name
7173
const int line; // Source line number
7274

7375
Exception(int exc, const char *exc_name, const char *f, int l)
7476
: num(exc), name(exc_name),
75-
msg(), errno_val(0),
77+
msg(), errno_val(0), ssl_err_code(0),
7678
file(f), line(l)
7779
{}
7880

7981
Exception(int exc, const char *exc_name,
8082
const std::string &m,
8183
const char *f, int l)
8284
: num(exc), name(exc_name),
83-
msg(m), errno_val(0),
85+
msg(m), errno_val(0), ssl_err_code(0),
86+
file(f), line(l)
87+
{}
88+
89+
Exception(int exc, const char *exc_name,
90+
int err, const char* m,
91+
int ssl_err,
92+
const char *f, int l)
93+
: num(exc), name(exc_name),
94+
msg(m), errno_val(err), ssl_err_code(ssl_err),
8495
file(f), line(l)
8596
{}
8697

8798
Exception(int exc, const char *exc_name,
8899
int err, const std::string &m,
100+
int ssl_err,
89101
const char *f, int l)
90102
: num(exc), name(exc_name),
91-
msg(m), errno_val(err),
103+
msg(m), errno_val(err), ssl_err_code(ssl_err),
92104
file(f), line(l)
93105
{}
94106
Exception() = delete;
95107
Exception(const Exception&) = default;
96108
Exception& operator=(const Exception&) = delete;
109+
friend std::ostream& operator<<(std::ostream&, const Exception&);
97110
};
98111

112+
std::ostream& operator<<(std::ostream&, const Exception&);
99113
};
100114

101115
#define THROW_EXCEPTION(name, ...) \

src/comm/Connection.cc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,10 +97,10 @@ const std::basic_string<uint8_t>& Connection::recv_message()
9797
};
9898

9999
size_t bytes_recv = recv_and_check(reinterpret_cast<uint8_t*>(&recv_message_size),
100-
sizeof(uint32_t));
100+
sizeof(recv_message_size));
101101

102102
if (bytes_recv != sizeof(recv_message_size)) {
103-
THROW_EXCEPTION(ReadFail);
103+
THROW_EXCEPTION(ReadFail, "Short read msg header");
104104
}
105105

106106
if (recv_message_size > _max_buffer_size) {
@@ -115,11 +115,11 @@ const std::basic_string<uint8_t>& Connection::recv_message()
115115
bytes_recv = recv_and_check(const_cast<uint8_t*>(_buffer_str.data()), recv_message_size);
116116

117117
if (recv_message_size != bytes_recv) {
118-
THROW_EXCEPTION(ReadFail);
118+
THROW_EXCEPTION(ReadFail, "Short read msg body");
119119
}
120120

121121
if (recv_message_size != _buffer_str.size()) {
122-
THROW_EXCEPTION(ReadFail);
122+
THROW_EXCEPTION(ReadFail, "Short read other");
123123
}
124124

125125
if (_metrics) {

src/comm/Exception.cc

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,12 @@
2828
*
2929
*/
3030

31+
#include "comm/Exception.h"
32+
3133
#include <stdio.h>
3234
#include <string.h>
33-
34-
#include "comm/Exception.h"
35+
#include <openssl/ssl.h>
36+
#include <openssl/err.h>
3537

3638
void print_exception(const comm::Exception &e, FILE *f)
3739
{
@@ -41,3 +43,59 @@ void print_exception(const comm::Exception &e, FILE *f)
4143
else if (!e.msg.empty())
4244
fprintf(f, "%s\n", e.msg.c_str());
4345
}
46+
47+
std::ostream& comm::operator<<(std::ostream& os, const comm::Exception& o)
48+
{
49+
static const size_t len = 255;
50+
char buf[len+1];
51+
buf[len] = 0;
52+
53+
os << o.file << ':' << o.line << ':'
54+
<< " comm::Exception={"
55+
<< "num=" << o.num
56+
<< ",name='" << o.name << "'"
57+
;
58+
if (!o.msg.empty()) {
59+
os << ",msg='" << o.msg << "'"
60+
;
61+
}
62+
int e = o.errno_val;
63+
if (e) {
64+
buf[0] = 0;
65+
os << ",Error={"
66+
<< "errno=" << e
67+
<< ",errmsg='" << strerror_r(e, buf, len) << "'"
68+
<< '}'
69+
;
70+
}
71+
auto s = o.ssl_err_code;
72+
if (s) {
73+
const char* err_str = "?";
74+
if (false) {
75+
# define _O(X) } else if (s == X) { err_str = #X;
76+
_O(SSL_ERROR_NONE)
77+
_O(SSL_ERROR_ZERO_RETURN)
78+
_O(SSL_ERROR_WANT_READ)
79+
_O(SSL_ERROR_WANT_WRITE)
80+
_O(SSL_ERROR_WANT_CONNECT)
81+
_O(SSL_ERROR_WANT_ACCEPT)
82+
_O(SSL_ERROR_WANT_X509_LOOKUP)
83+
_O(SSL_ERROR_WANT_ASYNC)
84+
_O(SSL_ERROR_WANT_ASYNC_JOB)
85+
_O(SSL_ERROR_WANT_CLIENT_HELLO_CB)
86+
_O(SSL_ERROR_SYSCALL)
87+
_O(SSL_ERROR_SSL)
88+
# undef _O
89+
}
90+
const char* r = ERR_reason_error_string(s);
91+
os << ",sslError={"
92+
<< "err=" << err_str
93+
<< ",reason='" << (r ? r : "") << "'"
94+
<< '}'
95+
;
96+
}
97+
os << '}';
98+
99+
return os;
100+
}
101+

src/comm/TCPConnection.cc

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,22 +59,25 @@ size_t TCPConnection::read(uint8_t* buffer, size_t length)
5959
THROW_EXCEPTION(SocketFail);
6060
}
6161

62+
errno = 0;
6263
auto count = ::recv(_tcp_socket->_socket_fd, buffer, length, MSG_WAITALL);
64+
int errno_r = errno;
6365

6466
if (count < 0) {
6567
DISABLE_WARNING(logical-op)
6668
if (errno == EAGAIN || errno == EWOULDBLOCK) {
67-
THROW_EXCEPTION(ConnectionShutDown, "Connection being cleaned cause of timeout");
69+
THROW_EXCEPTION(ConnectionShutDown, // Not, really. Read expired for blocking socket.
70+
errno_r, "recv()", 0);
6871
}
6972
else {
70-
THROW_EXCEPTION(ReadFail);
73+
THROW_EXCEPTION(ReadFail, errno_r, "recv()", 0);
7174
}
7275
ENABLE_WARNING(logical-op)
7376
}
7477
// When a stream socket peer has performed an orderly shutdown, the
7578
// return value will be 0 (the traditional "end-of-file" return).
7679
else if (count == 0) {
77-
THROW_EXCEPTION(ConnectionShutDown, "Closing Connection.");
80+
THROW_EXCEPTION(ConnectionShutDown, "Peer Closed Connection.");
7881
}
7982

8083
return static_cast<size_t>(count);

src/comm/TCPSocket.cc

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <netinet/ip.h>
1010
#include <sys/socket.h>
1111
#include <unistd.h>
12+
#include <glog/logging.h>
1213

1314
#include "comm/Exception.h"
1415
#include "comm/Variables.h"
@@ -27,19 +28,42 @@ TCPSocket::~TCPSocket()
2728
}
2829
}
2930

31+
static long msec_diff(const struct timespec& a,
32+
const struct timespec& b)
33+
{
34+
return
35+
(a.tv_sec - b.tv_sec) * 1000 +
36+
(a.tv_nsec - b.tv_nsec) / 1000000;
37+
}
38+
39+
3040
std::unique_ptr<TCPSocket> TCPSocket::accept(const std::unique_ptr<TCPSocket>& listening_socket)
3141
{
3242
struct sockaddr_in clnt_addr;
3343
socklen_t len = sizeof(clnt_addr); //store size of the address
3444

3545
// This is where client connects.
3646
// Server will stall here until incoming connection
37-
// unless the socket is marked and nonblocking
38-
int connected_socket = ::accept(listening_socket->_socket_fd, reinterpret_cast<sockaddr*>(&clnt_addr), &len);
47+
// unless the socket is marked as nonblocking
48+
again:
49+
timespec t1;
50+
clock_gettime(CLOCK_REALTIME_COARSE, &t1);
3951

52+
errno = 0;
53+
int connected_socket = ::accept(listening_socket->_socket_fd, reinterpret_cast<sockaddr*>(&clnt_addr), &len);
54+
int errno_r = errno;
4055
if (connected_socket < 0) {
41-
THROW_EXCEPTION(ConnectionError);
56+
if (errno_r == EAGAIN) {
57+
timespec t2;
58+
clock_gettime(CLOCK_REALTIME_COARSE, &t2);
59+
auto dt = msec_diff(t2, t1);
60+
VLOG(3) << "accept(): no activity for " << dt << " msec. Going back to listening";
61+
goto again;
62+
} else {
63+
THROW_EXCEPTION(ConnectionError, errno_r, "accept()", 0);
64+
}
4265
}
66+
// MAGICK can be done here
4367

4468
return std::unique_ptr<TCPSocket>(new TCPSocket(connected_socket));
4569
}

src/comm/TLSConnection.cc

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <netdb.h>
1111
#include <string>
1212
#include <unistd.h>
13+
#include <glog/logging.h>
1314

1415
#include "comm/Exception.h"
1516
#include "util/gcc_util.h"
@@ -31,35 +32,64 @@ TLSConnection::TLSConnection(
3132
{
3233
}
3334

35+
static long msec_diff(const struct timespec& a,
36+
const struct timespec& b)
37+
{
38+
return
39+
(a.tv_sec - b.tv_sec) * 1000 +
40+
(a.tv_nsec - b.tv_nsec) / 1000000;
41+
}
42+
3443
size_t TLSConnection::read(uint8_t* buffer, size_t length)
3544
{
45+
again:
46+
timespec t1;
47+
clock_gettime(CLOCK_REALTIME_COARSE, &t1);
48+
49+
errno = 0;
3650
auto count = SSL_read(_tls_socket->_ssl, buffer, length);
51+
int errno_r = errno;
3752

3853
if (count <= 0) {
3954
auto error = SSL_get_error(_tls_socket->_ssl, count);
4055

41-
DISABLE_WARNING(logical-op)
4256
if (error == SSL_ERROR_ZERO_RETURN) {
43-
THROW_EXCEPTION(ConnectionShutDown, "Closing Connection.");
57+
THROW_EXCEPTION(ConnectionShutDown, // FIXME -- misleading 'ConnectionShutDown'
58+
errno_r, "SSL_read()", error); // Peer closed conn for writing, so no more reads
4459
}
45-
else if (error == SSL_ERROR_SYSCALL && (!errno || errno == EAGAIN)) {
46-
THROW_EXCEPTION(ConnectionShutDown, "Closing Connection.");
60+
else if (error == SSL_ERROR_WANT_READ) {
61+
if (errno_r == EAGAIN) {
62+
timespec t2;
63+
clock_gettime(CLOCK_REALTIME_COARSE, &t2);
64+
auto dt = msec_diff(t2, t1);
65+
VLOG(3) << "SSL_read(): no activity for " << dt << " msec. Going back to reading";
66+
goto again;
67+
} else {
68+
// This error is recoverable. Consider handling it.
69+
THROW_EXCEPTION(ReadFail, errno_r, "SSL_read()", error);
70+
}
71+
}
72+
else if (error == SSL_ERROR_SYSCALL ||
73+
error == SSL_ERROR_SSL) {
74+
THROW_EXCEPTION(ConnectionShutDown, errno_r, "SSL_read()", error);
75+
// FIXME: *we* must close the conn
4776
}
4877
else {
49-
THROW_EXCEPTION(ReadFail);
78+
THROW_EXCEPTION(ReadFail, errno_r, "SSL_read()", error);
5079
}
51-
ENABLE_WARNING(logical-op)
5280
}
5381

5482
return static_cast<size_t>(count);
5583
}
5684

5785
size_t TLSConnection::write(const uint8_t* buffer, size_t length)
5886
{
87+
errno = 0;
5988
auto count = SSL_write(_tls_socket->_ssl, buffer, static_cast<int>(length));
60-
89+
int errno_r = errno;
6190
if (count <= 0) {
62-
THROW_EXCEPTION(WriteFail, "Error sending message.");
91+
auto error = SSL_get_error(_tls_socket->_ssl, count);
92+
THROW_EXCEPTION(WriteFail, errno_r, "SSL_write()", error);
6393
}
6494

6595
return static_cast<size_t>(count);

src/comm/TLSSocket.cc

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ TLSSocket::TLSSocket(std::unique_ptr<TCPSocket> tcp_socket, SSL* ssl) :
2525
TLSSocket::~TLSSocket()
2626
{
2727
if (_ssl) {
28-
if (!(SSL_get_shutdown(_ssl) & SSL_SENT_SHUTDOWN)) {
28+
int status = SSL_get_shutdown(_ssl);
29+
if ((status & (SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN)) == 0) {
2930
SSL_shutdown(_ssl);
3031
}
3132
SSL_free(_ssl);
@@ -34,21 +35,22 @@ TLSSocket::~TLSSocket()
3435

3536
void TLSSocket::accept()
3637
{
38+
errno = 0;
3739
auto result = ::SSL_accept(_ssl);
38-
40+
int errno_r = errno;
3941
if (result < 1) {
40-
THROW_EXCEPTION(TLSError,
41-
"Error accepting connection. SSL Error: " +
42-
std::to_string(result));
42+
THROW_EXCEPTION(TLSError, errno_r, "SSL_accept()", result);
4343
}
4444
}
4545

4646
void TLSSocket::connect()
4747
{
48+
errno = 0;
4849
auto result = ::SSL_connect(_ssl);
50+
int errno_r = errno;
4951

5052
if (result < 1) {
51-
THROW_EXCEPTION(TLSError);
53+
THROW_EXCEPTION(TLSError, errno_r, "SSL_connect()", result);
5254
}
5355
}
5456

tools/prometheus_ambassador/SConscript

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ prom_amb_env.Replace(
1818
'aperturedb-client',
1919
'prometheus-cpp-core',
2020
'prometheus-cpp-pull',
21+
'glog',
2122
],
2223
LIBPATH = [ '/usr/local/lib/',
2324
os.getenv('AD_COMM_LIB', default='../../lib'),
@@ -39,7 +40,7 @@ prom_amb_env.Program('prometheus_ambassador', src)
3940

4041
test_env = prom_amb_env.Clone()
4142
test_env.Replace(
42-
LIBS = prom_amb_env['LIBS'] + ['gtest', 'pthread', 'protobuf'],
43+
LIBS = prom_amb_env['LIBS'] + ['pthread', 'protobuf', 'gtest'],
4344
CPPPATH = prom_amb_env['CPPPATH'] + ['../../test', '../../src'],
4445
)
4546

0 commit comments

Comments
 (0)