WIP: Don't exit on SSL error

This commit is contained in:
Henry Case 2019-07-28 20:46:04 +01:00
parent a6601c1e97
commit 694bebfc54

View File

@ -1,31 +1,31 @@
/* /*
* Copyright (C) 2000-2007 Hewlett-Packard Company * Copyright (C) 2000-2007 Hewlett-Packard Company
* *
* This file is part of httperf, a web server performance measurment tool. * This file is part of httperf, a web server performance measurment tool.
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free * under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option) * Software Foundation; either version 2 of the License, or (at your option)
* any later version. * any later version.
* *
* In addition, as a special exception, the copyright holders give permission * In addition, as a special exception, the copyright holders give permission
* to link the code of this work with the OpenSSL project's "OpenSSL" library * to link the code of this work with the OpenSSL project's "OpenSSL" library
* (or with modified versions of it that use the same license as the "OpenSSL" * (or with modified versions of it that use the same license as the "OpenSSL"
* library), and distribute linked combinations including the two. You must * library), and distribute linked combinations including the two. You must
* obey the GNU General Public License in all respects for all of the code * obey the GNU General Public License in all respects for all of the code
* used other than "OpenSSL". If you modify this file, you may extend this * used other than "OpenSSL". If you modify this file, you may extend this
* exception to your version of the file, but you are not obligated to do so. * exception to your version of the file, but you are not obligated to do so.
* If you do not wish to do so, delete this exception statement from your * If you do not wish to do so, delete this exception statement from your
* version. * version.
* *
* This program is distributed in the hope that it will be useful, but WITHOUT * This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details. * more details.
* *
* You should have received a copy of the GNU General Public License along * You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., 51 * with this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/ */
#include "config.h" #include "config.h"
@ -200,7 +200,7 @@ hash_code(const char *server, size_t server_len, int port)
int ch; int ch;
/* /*
* Basically the ELF hash algorithm: * Basically the ELF hash algorithm:
*/ */
while ((ch = *cp++) != '\0') { while ((ch = *cp++) != '\0') {
@ -405,7 +405,7 @@ clear_active(Conn * s, enum IO_DIR dir)
} }
#else #else
fd_set * fdset; fd_set * fdset;
if (dir == WRITE) if (dir == WRITE)
fdset = &wrfds; fdset = &wrfds;
else else
@ -459,7 +459,7 @@ set_active(Conn * s, enum IO_DIR dir)
} }
#else #else
fd_set * fdset; fd_set * fdset;
if (dir == WRITE) if (dir == WRITE)
fdset = &wrfds; fdset = &wrfds;
else else
@ -564,7 +564,7 @@ do_send(Conn * conn)
break; break;
} else { } else {
/* /*
* we're done with this fragment: * we're done with this fragment:
*/ */
nsent -= iovp->iov_len; nsent -= iovp->iov_len;
*iovp = call->req.iov_saved; *iovp = call->req.iov_saved;
@ -575,7 +575,7 @@ do_send(Conn * conn)
call->req.iov_index = iovp - call->req.iov; call->req.iov_index = iovp - call->req.iov;
if (call->req.iov_index < NELEMS(call->req.iov)) { if (call->req.iov_index < NELEMS(call->req.iov)) {
/* /*
* there are more header bytes to write * there are more header bytes to write
*/ */
call->timeout = call->timeout =
param.timeout ? timer_now() + param.timeout : 0.0; param.timeout ? timer_now() + param.timeout : 0.0;
@ -584,7 +584,7 @@ do_send(Conn * conn)
} }
/* /*
* we're done with sending this request * we're done with sending this request
*/ */
conn->sendq = call->sendq_next; conn->sendq = call->sendq_next;
if (!conn->sendq) { if (!conn->sendq) {
@ -600,8 +600,8 @@ do_send(Conn * conn)
/* /*
* get ready to receive matching reply (note that we * get ready to receive matching reply (note that we
* implicitly pass on the reference to the call from the sendq * implicitly pass on the reference to the call from the sendq
* to the recvq): * to the recvq):
*/ */
call->recvq_next = 0; call->recvq_next = 0;
if (!conn->recvq) if (!conn->recvq)
@ -640,7 +640,7 @@ recv_done(Call * call)
conn->recvq_tail = 0; conn->recvq_tail = 0;
} }
/* /*
* we're done with receiving this request * we're done with receiving this request
*/ */
arg.l = 0; arg.l = 0;
event_signal(EV_CALL_RECV_STOP, (Object *) call, arg); event_signal(EV_CALL_RECV_STOP, (Object *) call, arg);
@ -697,7 +697,7 @@ do_recv(Conn * s)
if (DBG > 3) { if (DBG > 3) {
/* /*
* dump received data in hex & ascii: * dump received data in hex & ascii:
*/ */
fprintf(stderr, "do_recv.%lu: received reply data:\n", c->id); fprintf(stderr, "do_recv.%lu: received reply data:\n", c->id);
@ -718,7 +718,7 @@ do_recv(Conn * s)
} }
/* /*
* process the replies in this buffer: * process the replies in this buffer:
*/ */
buf_len = nread; buf_len = nread;
@ -727,7 +727,7 @@ do_recv(Conn * s)
c = s->recvq; c = s->recvq;
assert(c); assert(c);
/* /*
* sets right start time, but doesn't update each packet * sets right start time, but doesn't update each packet
*/ */
if (s->state == S_REPLY_STATUS) { if (s->state == S_REPLY_STATUS) {
c->timeout = param.timeout + param.think_timeout; c->timeout = param.timeout + param.think_timeout;
@ -951,7 +951,7 @@ core_init(void)
core_add_address(myaddr.sin_addr); core_add_address(myaddr.sin_addr);
/* /*
* Don't disturb just because a TCP connection closed on us... * Don't disturb just because a TCP connection closed on us...
*/ */
signal(SIGPIPE, SIG_IGN); signal(SIGPIPE, SIG_IGN);
@ -974,7 +974,7 @@ core_init(void)
fprintf(stderr, fprintf(stderr,
"%s: failed to add timer event: %s", prog_name, "%s: failed to add timer event: %s", prog_name,
strerror(errno)); strerror(errno));
} }
#else #else
#ifdef HAVE_EPOLL #ifdef HAVE_EPOLL
epoll_fd = epoll_create(EPOLL_N_MAX); epoll_fd = epoll_create(EPOLL_N_MAX);
@ -995,17 +995,17 @@ core_init(void)
#else #else
#ifdef DONT_POLL #ifdef DONT_POLL
/* /*
* This causes select() to take several milliseconds on both Linux/x86 * This causes select() to take several milliseconds on both Linux/x86
* and HP-UX 10.20. * and HP-UX 10.20.
*/ */
select_timeout.tv_sec = (u_long) TIMER_INTERVAL; select_timeout.tv_sec = (u_long) TIMER_INTERVAL;
select_timeout.tv_usec = (u_long) (TIMER_INTERVAL * 1e6); select_timeout.tv_usec = (u_long) (TIMER_INTERVAL * 1e6);
#else #else
/* /*
* This causes httperf to become a CPU hog as it polls for * This causes httperf to become a CPU hog as it polls for
* filedescriptors to become readable/writable. This is OK as long as * filedescriptors to become readable/writable. This is OK as long as
* httperf is the only (interesting) user-level process that executes * httperf is the only (interesting) user-level process that executes
* on a machine. * on a machine.
*/ */
select_timeout.tv_sec = 0; select_timeout.tv_sec = 0;
select_timeout.tv_usec = 0; select_timeout.tv_usec = 0;
@ -1014,7 +1014,7 @@ core_init(void)
#endif #endif
/* /*
* boost open file limit to the max: * boost open file limit to the max:
*/ */
if (getrlimit(RLIMIT_NOFILE, &rlimit) < 0) { if (getrlimit(RLIMIT_NOFILE, &rlimit) < 0) {
fprintf(stderr, fprintf(stderr,
@ -1048,7 +1048,7 @@ core_init(void)
#ifdef HAVE_SSL #ifdef HAVE_SSL
void int
core_ssl_connect(Conn * s) core_ssl_connect(Conn * s)
{ {
Any_Type arg; Any_Type arg;
@ -1083,13 +1083,13 @@ core_ssl_connect(Conn * s)
clear_active(s, READ); clear_active(s, READ);
set_active(s, WRITE); set_active(s, WRITE);
} }
return; return 0;
} }
fprintf(stderr, fprintf(stderr,
"%s: failed to connect to SSL server (err=%d, reason=%d)\n", "%s: failed to connect to SSL server (err=%d, reason=%d)\n",
prog_name, ssl_err, reason); prog_name, ssl_err, reason);
ERR_print_errors_fp(stderr); ERR_print_errors_fp(stderr);
exit(-1); return -1;
} }
s->state = S_CONNECTED; s->state = S_CONNECTED;
@ -1114,6 +1114,7 @@ core_ssl_connect(Conn * s)
arg.l = 0; arg.l = 0;
event_signal(EV_CONN_CONNECTED, (Object *) s, arg); event_signal(EV_CONN_CONNECTED, (Object *) s, arg);
return 0;
} }
#endif /* HAVE_SSL */ #endif /* HAVE_SSL */
@ -1168,7 +1169,7 @@ core_connect(Conn * s)
/* /*
* Disable Nagle algorithm so we don't delay needlessly when * Disable Nagle algorithm so we don't delay needlessly when
* pipelining requests. * pipelining requests.
*/ */
optval = 1; optval = 1;
if (setsockopt(sd, SOL_TCP, TCP_NODELAY, &optval, sizeof(optval)) < 0) { if (setsockopt(sd, SOL_TCP, TCP_NODELAY, &optval, sizeof(optval)) < 0) {
@ -1267,7 +1268,12 @@ core_connect(Conn * s)
if (result == 0) { if (result == 0) {
#ifdef HAVE_SSL #ifdef HAVE_SSL
if (param.use_ssl) if (param.use_ssl)
core_ssl_connect(s); printf("OZAPTF UNKNOWN case\n");
if (core_ssl_connect(s) == -1) {
// OZAPTF:
conn_failure(s, errno);
return -1;
}
else else
#endif #endif
{ {
@ -1279,7 +1285,7 @@ core_connect(Conn * s)
/* /*
* The socket becomes writable only after the connection has * The socket becomes writable only after the connection has
* been established. Hence we wait for writability to detect * been established. Hence we wait for writability to detect
* connection establishment. * connection establishment.
*/ */
s->state = S_CONNECTING; s->state = S_CONNECTING;
set_active(s, WRITE); set_active(s, WRITE);
@ -1325,7 +1331,7 @@ core_send(Conn * conn, Call * call)
call->req.iov[IE_HOST].iov_len = 0; call->req.iov[IE_HOST].iov_len = 0;
} else if (!call->req.iov[IE_HOST].iov_base) { } else if (!call->req.iov[IE_HOST].iov_base) {
/* /*
* Default call's hostname to connection's hostname: * Default call's hostname to connection's hostname:
*/ */
call->req.iov[IE_HOST].iov_base = (caddr_t) conn->fqdname; call->req.iov[IE_HOST].iov_base = (caddr_t) conn->fqdname;
call->req.iov[IE_HOST].iov_len = conn->fqdname_len; call->req.iov[IE_HOST].iov_len = conn->fqdname_len;
@ -1336,7 +1342,7 @@ core_send(Conn * conn, Call * call)
* understand. If we send HTTP/1.1, it doesn't mean that the server * understand. If we send HTTP/1.1, it doesn't mean that the server
* has to speak HTTP/1.1. In other words, sending an HTTP/1.1 header * has to speak HTTP/1.1. In other words, sending an HTTP/1.1 header
* leaves it up to the server whether it wants to reply with a 1.0 or * leaves it up to the server whether it wants to reply with a 1.0 or
* 1.1 reply. * 1.1 reply.
*/ */
switch (call->req.version) { switch (call->req.version) {
case 0x10000: case 0x10000:
@ -1373,7 +1379,7 @@ core_send(Conn * conn, Call * call)
call->req.iov_saved = call->req.iov[0]; call->req.iov_saved = call->req.iov[0];
/* /*
* insert call into connection's send queue: * insert call into connection's send queue:
*/ */
call_inc_ref(call); call_inc_ref(call);
call->sendq_next = 0; call->sendq_next = 0;
@ -1413,7 +1419,7 @@ core_close(Conn * conn)
} }
/* /*
* first, get rid of all pending calls: * first, get rid of all pending calls:
*/ */
for (call = conn->sendq; call; call = call_next) { for (call = conn->sendq; call; call = call_next) {
call_next = call->sendq_next; call_next = call->sendq_next;
@ -1464,14 +1470,15 @@ core_close(Conn * conn)
port_put(conn->myaddr, conn->myport); port_put(conn->myaddr, conn->myport);
/* /*
* A connection that has been closed is not useful anymore, so we give * A connection that has been closed is not useful anymore, so we give
* up the reference obtained when creating the session. This normally * up the reference obtained when creating the session. This normally
* initiates destruction of the connection. * initiates destruction of the connection.
*/ */
conn_dec_ref(conn); conn_dec_ref(conn);
} }
#ifdef HAVE_KEVENT #ifdef HAVE_KEVENT
#error "MUST NOT BE USED"
void void
core_loop(void) core_loop(void)
{ {
@ -1521,7 +1528,7 @@ core_loop(void)
if (ev.filter == EVFILT_READ && conn->recvq) if (ev.filter == EVFILT_READ && conn->recvq)
do_recv(conn); do_recv(conn);
} }
conn_dec_ref(conn); conn_dec_ref(conn);
break; break;
} }
@ -1559,7 +1566,11 @@ core_loop(void)
if (conn->state == S_CONNECTING) { if (conn->state == S_CONNECTING) {
#ifdef HAVE_SSL #ifdef HAVE_SSL
if (param.use_ssl) if (param.use_ssl)
core_ssl_connect(conn); if (core_ssl_connect(conn) == -1) {
event_signal(EV_CONN_TIMEOUT, (Object*)conn, arg);
conn_dec_ref(conn);
continue;
}
else else
#endif #endif
if (ep->events & EPOLLOUT) { if (ep->events & EPOLLOUT) {
@ -1580,6 +1591,9 @@ core_loop(void)
close(epoll_fd); close(epoll_fd);
} }
#else #else
#error "MUST NOT BE USED"
void void
core_loop(void) core_loop(void)
{ {
@ -1588,7 +1602,7 @@ core_loop(void)
fd_mask mask; fd_mask mask;
Any_Type arg; Any_Type arg;
Conn *conn; Conn *conn;
while (running) { while (running) {
struct timeval tv = select_timeout; struct timeval tv = select_timeout;
@ -1614,7 +1628,7 @@ core_loop(void)
while (n > 0) { while (n > 0) {
/* /*
* find the index of the fdmask that has something * find the index of the fdmask that has something
* going on: * going on:
*/ */
do { do {
++i; ++i;
@ -1631,7 +1645,7 @@ core_loop(void)
--n; --n;
is_readable = (FD_ISSET(sd, &readable) && FD_ISSET(sd, &rdfds)); is_readable = (FD_ISSET(sd, &readable) && FD_ISSET(sd, &rdfds));
is_writable = (FD_ISSET(sd, &writable) && FD_ISSET(sd, &wrfds)); is_writable = (FD_ISSET(sd, &writable) && FD_ISSET(sd, &wrfds));
if (is_readable || is_writable) { if (is_readable || is_writable) {
/* /*
* only handle sockets that * only handle sockets that
@ -1646,8 +1660,11 @@ core_loop(void)
} }
if (conn->state == S_CONNECTING) { if (conn->state == S_CONNECTING) {
#ifdef HAVE_SSL #ifdef HAVE_SSL
if (param.use_ssl) if (param.use_ssl) {
core_ssl_connect(conn); core_ssl_connect(conn);
assert(false); /// OZAPTF: ensure this is not used
}
else else
#endif #endif
if (is_writable) { if (is_writable) {
@ -1662,9 +1679,9 @@ core_loop(void)
if (is_readable && conn->recvq) if (is_readable && conn->recvq)
do_recv(conn); do_recv(conn);
} }
conn_dec_ref(conn); conn_dec_ref(conn);
if (n > 0) if (n > 0)
timer_tick(); timer_tick();
} }