Lots of work on removing malloc from driver
This commit is contained in:
@@ -1,3 +1,6 @@
|
||||
#define OPENSSL_HEAP_SIZE (4*1024*1024)
|
||||
#define CHBUF_SIZE (256*1024)
|
||||
#define POLLVEC_SIZE (DrivenEngine::MAX_CHAN+1)
|
||||
|
||||
static MonoClock monoclock;
|
||||
|
||||
@@ -7,7 +10,7 @@ namespace util {
|
||||
}
|
||||
}
|
||||
|
||||
static void if_error_print_and_exit(const std::string &str) {
|
||||
static void if_error_print_and_exit(const UmmString &str) {
|
||||
if (!str.empty()) {
|
||||
std::cerr << std::endl << "error: " << str << std::endl;
|
||||
exit(1);
|
||||
@@ -28,12 +31,12 @@ static SSL_CTX *new_ssl_context(bool server_cert, bool root_certs, const std::st
|
||||
return ctx;
|
||||
}
|
||||
|
||||
static std::string err_print_errors_str() {
|
||||
static UmmString err_print_errors_str() {
|
||||
BIO *bio = BIO_new(BIO_s_mem());
|
||||
ERR_print_errors(bio);
|
||||
char *buf;
|
||||
size_t len = BIO_get_mem_data(bio, &buf);
|
||||
std::string ret(buf, len);
|
||||
UmmString ret(buf, len);
|
||||
BIO_free(bio);
|
||||
return ret;
|
||||
}
|
||||
@@ -58,8 +61,12 @@ static int ssl_ctx_use_privatekey_str(SSL_CTX *ctx, const char *str) {
|
||||
return status;
|
||||
}
|
||||
|
||||
static std::unique_ptr<char[]> chbuf;
|
||||
static std::unique_ptr<struct pollfd[]> pollvec;
|
||||
|
||||
class Driver {
|
||||
public:
|
||||
|
||||
enum ChanState {
|
||||
CHAN_INACTIVE,
|
||||
CHAN_PLAINTEXT,
|
||||
@@ -87,19 +94,18 @@ public:
|
||||
DrivenEngine *driven_;
|
||||
std::vector<ChanInfo> chans_;
|
||||
std::map<int, SOCKET> listen_sockets_;
|
||||
std::unique_ptr<char[]> chbuf;
|
||||
bool read_console_recently_;
|
||||
|
||||
SSL_CTX *ssl_ctx_with_root_certs_;
|
||||
SSL_CTX *ssl_ctx_with_server_certs_;
|
||||
SSL_CTX *ssl_ctx_with_no_certs_;
|
||||
|
||||
|
||||
void handle_listen_ports() {
|
||||
std::set<int> listenports;
|
||||
driven_->drv_get_listen_ports(listenports);
|
||||
const std::vector<int> &listenports = driven_->drv_get_listen_ports();
|
||||
for (int port : listenports) {
|
||||
if (listen_sockets_.find(port) == listen_sockets_.end()) {
|
||||
std::string err;
|
||||
UmmString err;
|
||||
SOCKET sock = listen_on_port(port, err);
|
||||
if_error_print_and_exit(err);
|
||||
assert(sock != INVALID_SOCKET);
|
||||
@@ -114,7 +120,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void close_channel(ChanInfo &chan, const std::string &err) {
|
||||
void close_channel(ChanInfo &chan, std::string_view err) {
|
||||
// std::cerr << "Closing channel " << chan.chid << std::endl;
|
||||
assert(chan.state != CHAN_INACTIVE);
|
||||
// Close and release the SSL channel.
|
||||
@@ -196,10 +202,9 @@ public:
|
||||
}
|
||||
|
||||
void handle_new_outgoing_sockets() {
|
||||
std::set<int> chans;
|
||||
driven_->drv_get_new_outgoing(chans);
|
||||
const std::vector<int> &chans = driven_->drv_get_new_outgoing();
|
||||
for (int chid : chans) {
|
||||
std::string err;
|
||||
UmmString err;
|
||||
SOCKET sock = open_connection(driven_->drv_get_target(chid), err);
|
||||
if (sock == INVALID_SOCKET) {
|
||||
driven_->drv_notify_close(chid, err);
|
||||
@@ -208,10 +213,13 @@ public:
|
||||
make_channel(sock, chid, ssl_ctx_with_no_certs_, CHAN_SSL_CONNECTING);
|
||||
}
|
||||
}
|
||||
if (!chans.empty()) {
|
||||
driven_->drv_clear_new_outgoing();
|
||||
}
|
||||
}
|
||||
|
||||
void accept_connection(int port, SOCKET sock) {
|
||||
std::string err;
|
||||
UmmString err;
|
||||
SOCKET socket = accept_on_socket(sock, err);
|
||||
if_error_print_and_exit(err);
|
||||
if (socket != INVALID_SOCKET) {
|
||||
@@ -222,7 +230,7 @@ public:
|
||||
}
|
||||
|
||||
void advance_plaintext(ChanInfo &chan) {
|
||||
std::string err;
|
||||
UmmString err;
|
||||
|
||||
// If the channel has no outgoing bytes and has been released,
|
||||
// just close it.
|
||||
@@ -359,8 +367,8 @@ public:
|
||||
|
||||
|
||||
void handle_socket_input_output() {
|
||||
std::string err;
|
||||
int mstimeout = 1000;
|
||||
UmmString err;
|
||||
int mstimeout = read_console_recently_ ? 100 : 1000;
|
||||
|
||||
// Peek output buffers and determine channel release flags.
|
||||
for (ChanInfo &chan : chans_) {
|
||||
@@ -373,17 +381,15 @@ public:
|
||||
}
|
||||
|
||||
// Construct the struct pollfd vector.
|
||||
int pollsize = listen_sockets_.size() + chans_.size() + 1;
|
||||
PollVector pollvec(pollsize);
|
||||
int index = 0;
|
||||
int pollsize = 0;
|
||||
for (const auto &p : listen_sockets_) {
|
||||
struct pollfd &pfd = pollvec[index++];
|
||||
struct pollfd &pfd = pollvec[pollsize++];
|
||||
pfd.fd = p.second;
|
||||
pfd.events = POLLIN;
|
||||
pfd.revents = 0;
|
||||
}
|
||||
for (const ChanInfo &chan : chans_) {
|
||||
struct pollfd &pfd = pollvec[index++];
|
||||
struct pollfd &pfd = pollvec[pollsize++];
|
||||
assert(chan.socket != INVALID_SOCKET);
|
||||
pfd.fd = chan.socket;
|
||||
pfd.events = 0;
|
||||
@@ -395,14 +401,13 @@ public:
|
||||
if (chan.ready_on_outgoing && (chan.nbytes > 0)) pfd.events |= POLLOUT;
|
||||
// std::cerr << "evt=" << pfd.events << ".nb=" << chan.nbytes << " ";
|
||||
}
|
||||
fill_stdio_pollfd(pollvec, mstimeout, read_console_recently_);
|
||||
|
||||
// Do the poll.
|
||||
socket_poll(pollvec, mstimeout, err);
|
||||
socket_poll(pollvec.get(), pollsize, mstimeout, err);
|
||||
if_error_print_and_exit(err);
|
||||
|
||||
// Check listening sockets.
|
||||
index = 0;
|
||||
int index = 0;
|
||||
for (auto &p : listen_sockets_) {
|
||||
struct pollfd &pfd = pollvec[index++];
|
||||
if (pfd.revents & (POLLIN | POLLERR)) {
|
||||
@@ -435,14 +440,8 @@ public:
|
||||
}
|
||||
|
||||
void drive(DrivenEngine *de, int argc, char *argv[]) {
|
||||
disable_randomization(argc, argv);
|
||||
socket_init();
|
||||
SSL_load_error_strings();
|
||||
ERR_load_crypto_strings();
|
||||
enable_tty_raw();
|
||||
driven_ = de;
|
||||
read_console_recently_ = false;
|
||||
chbuf.reset(new char[65536]);
|
||||
|
||||
ssl_ctx_with_root_certs_ = new_ssl_context(false, true, "");
|
||||
ssl_ctx_with_server_certs_ = new_ssl_context(true, false, "");
|
||||
@@ -480,13 +479,33 @@ public:
|
||||
SSL_CTX_free(ssl_ctx_with_root_certs_);
|
||||
SSL_CTX_free(ssl_ctx_with_server_certs_);
|
||||
DrivenEngine::set(nullptr);
|
||||
socket_uninit();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void driver_drive(DrivenEngine *de, int argc, char *argv[]) {
|
||||
void driver_drive(int argc, char *argv[]) {
|
||||
// The only place in the driver where we're allowed to use malloc
|
||||
// is here, before even looking at the arguments. That way, the
|
||||
// impact on the malloc heap is always exactly the same, which
|
||||
// doesn't break the determinism of the execution during replay.
|
||||
|
||||
umm_init_heap(malloc(OPENSSL_HEAP_SIZE), OPENSSL_HEAP_SIZE);
|
||||
CRYPTO_set_mem_functions(umm_malloc_ssl, umm_realloc_ssl, umm_free_ssl);
|
||||
chbuf.reset(new char[CHBUF_SIZE]);
|
||||
pollvec.reset(new struct pollfd[POLLVEC_SIZE]);
|
||||
ERR_load_crypto_strings();
|
||||
SSL_load_error_strings();
|
||||
|
||||
Driver driver;
|
||||
driver.drive(de, argc, argv);
|
||||
if (argc < 2) {
|
||||
DrivenEngine::print_usage(std::cerr, argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
UniqueDrivenEngine engine = DrivenEngine::make(argv[1]);
|
||||
if (engine == nullptr) {
|
||||
DrivenEngine::print_usage(std::cerr, argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
driver.drive(engine.get(), argc, argv);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user