enhanced watcher manipulation when handling ssl connections
This commit is contained in:
parent
a0d68ad079
commit
87c5ebd303
@ -262,7 +262,7 @@ static struct sck_type_map_t sck_type_map[] =
|
|||||||
|
|
||||||
/* ======================================================================== */
|
/* ======================================================================== */
|
||||||
|
|
||||||
static void tmr_connect_handle (stio_t* stio, const stio_ntime_t* now, stio_tmrjob_t* job)
|
static void connect_timedout (stio_t* stio, const stio_ntime_t* now, stio_tmrjob_t* job)
|
||||||
{
|
{
|
||||||
stio_dev_sck_t* rdev = (stio_dev_sck_t*)job->ctx;
|
stio_dev_sck_t* rdev = (stio_dev_sck_t*)job->ctx;
|
||||||
|
|
||||||
@ -303,16 +303,13 @@ static void ssl_connect_timedout (stio_t* stio, const stio_ntime_t* now, stio_tm
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int schedule_timer_job (stio_dev_sck_t* dev, const stio_ntime_t* tmout, stio_tmrjob_handler_t handler)
|
static int schedule_timer_job_at (stio_dev_sck_t* dev, const stio_ntime_t* fire_at, stio_tmrjob_handler_t handler)
|
||||||
{
|
{
|
||||||
stio_tmrjob_t tmrjob;
|
stio_tmrjob_t tmrjob;
|
||||||
|
|
||||||
STIO_ASSERT (stio_ispostime(tmout));
|
|
||||||
|
|
||||||
STIO_MEMSET (&tmrjob, 0, STIO_SIZEOF(tmrjob));
|
STIO_MEMSET (&tmrjob, 0, STIO_SIZEOF(tmrjob));
|
||||||
tmrjob.ctx = dev;
|
tmrjob.ctx = dev;
|
||||||
stio_gettime (&tmrjob.when);
|
tmrjob.when = *fire_at;
|
||||||
stio_addtime (&tmrjob.when, tmout, &tmrjob.when);
|
|
||||||
|
|
||||||
tmrjob.handler = handler;
|
tmrjob.handler = handler;
|
||||||
tmrjob.idxptr = &dev->tmrjob_index;
|
tmrjob.idxptr = &dev->tmrjob_index;
|
||||||
@ -321,6 +318,19 @@ static int schedule_timer_job (stio_dev_sck_t* dev, const stio_ntime_t* tmout, s
|
|||||||
dev->tmrjob_index = stio_instmrjob (dev->stio, &tmrjob);
|
dev->tmrjob_index = stio_instmrjob (dev->stio, &tmrjob);
|
||||||
return dev->tmrjob_index == STIO_TMRIDX_INVALID? -1: 0;
|
return dev->tmrjob_index == STIO_TMRIDX_INVALID? -1: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int schedule_timer_job_after (stio_dev_sck_t* dev, const stio_ntime_t* fire_after, stio_tmrjob_handler_t handler)
|
||||||
|
{
|
||||||
|
stio_ntime_t fire_at;
|
||||||
|
|
||||||
|
STIO_ASSERT (stio_ispostime(fire_after));
|
||||||
|
|
||||||
|
stio_gettime (&fire_at);
|
||||||
|
stio_addtime (&fire_at, fire_after, &fire_at);
|
||||||
|
|
||||||
|
return schedule_timer_job_at (dev, &fire_at, handler);
|
||||||
|
}
|
||||||
|
|
||||||
/* ======================================================================== */
|
/* ======================================================================== */
|
||||||
|
|
||||||
static int dev_sck_make (stio_dev_t* dev, void* ctx)
|
static int dev_sck_make (stio_dev_t* dev, void* ctx)
|
||||||
@ -587,9 +597,12 @@ static int dev_sck_write_stateless (stio_dev_t* dev, const void* data, stio_iole
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if defined(USE_SSL)
|
#if defined(USE_SSL)
|
||||||
static int connect_ssl (stio_dev_sck_t* dev)
|
|
||||||
|
static int do_ssl (stio_dev_sck_t* dev, int (*ssl_func)(SSL*))
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
int watcher_cmd;
|
||||||
|
int watcher_events;
|
||||||
|
|
||||||
STIO_ASSERT (dev->ssl_ctx);
|
STIO_ASSERT (dev->ssl_ctx);
|
||||||
|
|
||||||
@ -606,75 +619,61 @@ static int connect_ssl (stio_dev_sck_t* dev)
|
|||||||
|
|
||||||
if (SSL_set_fd (ssl, dev->sck) == 0)
|
if (SSL_set_fd (ssl, dev->sck) == 0)
|
||||||
{
|
{
|
||||||
SSL_free (ssl);
|
|
||||||
dev->stio->errnum = STIO_ESYSERR;
|
dev->stio->errnum = STIO_ESYSERR;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
SSL_set_read_ahead (ssl, 0);
|
SSL_set_read_ahead (ssl, 0);
|
||||||
|
|
||||||
dev->ssl = ssl;
|
dev->ssl = ssl;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = SSL_connect (dev->ssl);
|
watcher_cmd = STIO_DEV_WATCH_RENEW;
|
||||||
|
watcher_events = 0;
|
||||||
|
|
||||||
|
ret = ssl_func ((SSL*)dev->ssl);
|
||||||
if (ret <= 0)
|
if (ret <= 0)
|
||||||
{
|
{
|
||||||
int err = SSL_get_error (dev->ssl, ret);
|
int err = SSL_get_error (dev->ssl, ret);
|
||||||
if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE)
|
if (err == SSL_ERROR_WANT_READ)
|
||||||
{
|
{
|
||||||
/* handshaking isn't complete */
|
/* handshaking isn't complete */
|
||||||
return 0;
|
ret = 0;
|
||||||
}
|
}
|
||||||
|
else if (err == SSL_ERROR_WANT_WRITE)
|
||||||
dev->stio->errnum = STIO_ESYSERR;
|
{
|
||||||
return -1;
|
/* handshaking isn't complete */
|
||||||
|
watcher_cmd = STIO_DEV_WATCH_UPDATE;
|
||||||
|
watcher_events = STIO_DEV_EVENT_IN | STIO_DEV_EVENT_OUT;
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dev->stio->errnum = STIO_ESYSERR;
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = 1; /* accepted */
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1; /* connected */
|
if (stio_dev_watch ((stio_dev_t*)dev, watcher_cmd, watcher_events) <= -1)
|
||||||
|
{
|
||||||
|
stio_stop (dev->stio, STIO_STOPREQ_WATCHER_ERROR);
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static STIO_INLINE int connect_ssl (stio_dev_sck_t* dev)
|
||||||
static int accept_ssl (stio_dev_sck_t* dev)
|
|
||||||
{
|
{
|
||||||
int ret;
|
return do_ssl (dev, SSL_connect);
|
||||||
|
}
|
||||||
|
|
||||||
STIO_ASSERT (dev->ssl_ctx);
|
static STIO_INLINE int accept_ssl (stio_dev_sck_t* dev)
|
||||||
|
{
|
||||||
if (!dev->ssl)
|
return do_ssl (dev, SSL_accept);
|
||||||
{
|
|
||||||
SSL* ssl;
|
|
||||||
|
|
||||||
ssl = SSL_new (dev->ssl_ctx);
|
|
||||||
if (!ssl)
|
|
||||||
{
|
|
||||||
dev->stio->errnum = STIO_ESYSERR;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SSL_set_fd (ssl, dev->sck) == 0)
|
|
||||||
{
|
|
||||||
dev->stio->errnum = STIO_ESYSERR;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
SSL_set_read_ahead (ssl, 0);
|
|
||||||
|
|
||||||
dev->ssl = ssl;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = SSL_accept ((SSL*)dev->ssl);
|
|
||||||
if (ret <= 0)
|
|
||||||
{
|
|
||||||
int err = SSL_get_error (dev->ssl, ret);
|
|
||||||
if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE)
|
|
||||||
{
|
|
||||||
/* handshaking isn't complete */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
dev->stio->errnum = STIO_ESYSERR;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1; /* accepted */
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -794,8 +793,8 @@ static int dev_sck_ioctl (stio_dev_t* dev, int cmd, void* arg)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_SSLv2); /* no outdated SSLv2 by default */
|
|
||||||
SSL_CTX_set_read_ahead (ssl_ctx, 0);
|
SSL_CTX_set_read_ahead (ssl_ctx, 0);
|
||||||
|
SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_SSLv2); /* no outdated SSLv2 by default */
|
||||||
|
|
||||||
rdev->tmout = bnd->accept_tmout;
|
rdev->tmout = bnd->accept_tmout;
|
||||||
#else
|
#else
|
||||||
@ -878,6 +877,8 @@ static int dev_sck_ioctl (stio_dev_t* dev, int cmd, void* arg)
|
|||||||
rdev->stio->errnum = STIO_ESYSERR;
|
rdev->stio->errnum = STIO_ESYSERR;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SSL_CTX_set_read_ahead (ssl_ctx, 0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
/*{
|
/*{
|
||||||
@ -898,18 +899,26 @@ fcntl (rdev->sck, F_SETFL, flags | O_NONBLOCK);
|
|||||||
if (stio_dev_watch ((stio_dev_t*)rdev, STIO_DEV_WATCH_UPDATE, STIO_DEV_EVENT_IN | STIO_DEV_EVENT_OUT) <= -1)
|
if (stio_dev_watch ((stio_dev_t*)rdev, STIO_DEV_WATCH_UPDATE, STIO_DEV_EVENT_IN | STIO_DEV_EVENT_OUT) <= -1)
|
||||||
{
|
{
|
||||||
/* watcher update failure. it's critical */
|
/* watcher update failure. it's critical */
|
||||||
stio_stop (rdev->stio, STIO_STOPREQ_WATCHER_UPDATE_ERROR);
|
stio_stop (rdev->stio, STIO_STOPREQ_WATCHER_ERROR);
|
||||||
goto oops_connect;
|
goto oops_connect;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (stio_ispostime(&conn->connect_tmout) &&
|
stio_inittime (&rdev->tmout, 0, 0); /* just in case */
|
||||||
schedule_timer_job (rdev, &conn->connect_tmout, tmr_connect_handle) <= -1)
|
|
||||||
|
if (stio_ispostime(&conn->connect_tmout))
|
||||||
{
|
{
|
||||||
goto oops_connect;
|
if (schedule_timer_job_after (rdev, &conn->connect_tmout, connect_timedout) <= -1)
|
||||||
|
{
|
||||||
|
goto oops_connect;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* update rdev->tmout to the deadline of the connect timeout job */
|
||||||
|
stio_gettmrjobdeadline (rdev->stio, rdev->tmrjob_index, &rdev->tmout);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rdev->tmout = conn->connect_tmout;
|
|
||||||
rdev->remoteaddr = conn->remoteaddr;
|
rdev->remoteaddr = conn->remoteaddr;
|
||||||
rdev->on_connect = conn->on_connect;
|
rdev->on_connect = conn->on_connect;
|
||||||
rdev->on_disconnect = conn->on_disconnect;
|
rdev->on_disconnect = conn->on_disconnect;
|
||||||
@ -927,7 +936,7 @@ fcntl (rdev->sck, F_SETFL, flags | O_NONBLOCK);
|
|||||||
if (stio_dev_watch ((stio_dev_t*)rdev, STIO_DEV_WATCH_UPDATE, STIO_DEV_EVENT_IN) <= -1)
|
if (stio_dev_watch ((stio_dev_t*)rdev, STIO_DEV_WATCH_UPDATE, STIO_DEV_EVENT_IN) <= -1)
|
||||||
{
|
{
|
||||||
/* watcher update failure. it's critical */
|
/* watcher update failure. it's critical */
|
||||||
stio_stop (rdev->stio, STIO_STOPREQ_WATCHER_UPDATE_ERROR);
|
stio_stop (rdev->stio, STIO_STOPREQ_WATCHER_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(USE_SSL)
|
#if defined(USE_SSL)
|
||||||
@ -963,8 +972,11 @@ fcntl (rdev->sck, F_SETFL, flags | O_NONBLOCK);
|
|||||||
if (x == 0)
|
if (x == 0)
|
||||||
{
|
{
|
||||||
STIO_ASSERT (rdev->tmrjob_index == STIO_TMRIDX_INVALID);
|
STIO_ASSERT (rdev->tmrjob_index == STIO_TMRIDX_INVALID);
|
||||||
|
|
||||||
|
/* it's ok to use conn->connect_tmout for ssl-connect as
|
||||||
|
* the underlying socket connection has been established immediately */
|
||||||
if (stio_ispostime(&conn->connect_tmout) &&
|
if (stio_ispostime(&conn->connect_tmout) &&
|
||||||
schedule_timer_job (rdev, &conn->connect_tmout, ssl_connect_timedout) <= -1)
|
schedule_timer_job_after (rdev, &conn->connect_tmout, ssl_connect_timedout) <= -1)
|
||||||
{
|
{
|
||||||
/* no device halting in spite of failure.
|
/* no device halting in spite of failure.
|
||||||
* let the caller handle this after having
|
* let the caller handle this after having
|
||||||
@ -1055,7 +1067,6 @@ static stio_dev_mth_t dev_sck_methods_stateful =
|
|||||||
dev_sck_ioctl, /* ioctl */
|
dev_sck_ioctl, /* ioctl */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static stio_dev_mth_t dev_mth_clisck =
|
static stio_dev_mth_t dev_mth_clisck =
|
||||||
{
|
{
|
||||||
dev_sck_make_client,
|
dev_sck_make_client,
|
||||||
@ -1100,7 +1111,7 @@ static int harvest_outgoing_connection (stio_dev_sck_t* rdev)
|
|||||||
if (stio_dev_watch ((stio_dev_t*)rdev, STIO_DEV_WATCH_RENEW, 0) <= -1)
|
if (stio_dev_watch ((stio_dev_t*)rdev, STIO_DEV_WATCH_RENEW, 0) <= -1)
|
||||||
{
|
{
|
||||||
/* watcher update failure. it's critical */
|
/* watcher update failure. it's critical */
|
||||||
stio_stop (rdev->stio, STIO_STOPREQ_WATCHER_RENEW_ERROR);
|
stio_stop (rdev->stio, STIO_STOPREQ_WATCHER_ERROR);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1119,10 +1130,11 @@ static int harvest_outgoing_connection (stio_dev_sck_t* rdev)
|
|||||||
|
|
||||||
STIO_ASSERT (rdev->tmrjob_index == STIO_TMRIDX_INVALID);
|
STIO_ASSERT (rdev->tmrjob_index == STIO_TMRIDX_INVALID);
|
||||||
|
|
||||||
/* TODO: calculate the timeout again... it should be (rdev->tmout - (now - socket-creation-time))
|
/* rdev->tmout has been set to the deadline of the connect task
|
||||||
* without the fix, timeout gets doubled. it's used for connect() once and for ssl-connect().*/
|
* when the CONNECT IOCTL command has been executed. use the
|
||||||
|
* same dead line here */
|
||||||
if (stio_ispostime(&rdev->tmout) &&
|
if (stio_ispostime(&rdev->tmout) &&
|
||||||
schedule_timer_job (rdev, &rdev->tmout, ssl_connect_timedout) <= -1)
|
schedule_timer_job_at (rdev, &rdev->tmout, ssl_connect_timedout) <= -1)
|
||||||
{
|
{
|
||||||
stio_dev_halt ((stio_dev_t*)rdev);
|
stio_dev_halt ((stio_dev_t*)rdev);
|
||||||
}
|
}
|
||||||
@ -1253,7 +1265,7 @@ static int accept_incoming_connection (stio_dev_sck_t* rdev)
|
|||||||
clidev->ssl_ctx = rdev->ssl_ctx;
|
clidev->ssl_ctx = rdev->ssl_ctx;
|
||||||
|
|
||||||
if (stio_ispostime(&rdev->tmout) &&
|
if (stio_ispostime(&rdev->tmout) &&
|
||||||
schedule_timer_job (clidev, &rdev->tmout, ssl_accept_timedout) <= -1)
|
schedule_timer_job_after (clidev, &rdev->tmout, ssl_accept_timedout) <= -1)
|
||||||
{
|
{
|
||||||
/* TODO: call a warning/error callback */
|
/* TODO: call a warning/error callback */
|
||||||
/* timer job scheduling failed. halt the device */
|
/* timer job scheduling failed. halt the device */
|
||||||
|
@ -229,12 +229,6 @@ struct stio_dev_sck_t
|
|||||||
stio_dev_sck_type_t type;
|
stio_dev_sck_type_t type;
|
||||||
stio_sckhnd_t sck;
|
stio_sckhnd_t sck;
|
||||||
|
|
||||||
/* connect timeout, ssl-connect timeout, ssl-accept timeout */
|
|
||||||
stio_ntime_t tmout;
|
|
||||||
|
|
||||||
void* ssl_ctx;
|
|
||||||
void* ssl;
|
|
||||||
|
|
||||||
int state;
|
int state;
|
||||||
|
|
||||||
/* remote peer address for a stateful stream socket. valid if one of the
|
/* remote peer address for a stateful stream socket. valid if one of the
|
||||||
@ -243,6 +237,7 @@ struct stio_dev_sck_t
|
|||||||
* STIO_DEV_TCP_ACCEPTED
|
* STIO_DEV_TCP_ACCEPTED
|
||||||
* STIO_DEV_TCP_CONNECTED
|
* STIO_DEV_TCP_CONNECTED
|
||||||
* STIO_DEV_TCP_CONNECTING
|
* STIO_DEV_TCP_CONNECTING
|
||||||
|
* STIO_DEV_TCP_CONNECTING_SSL
|
||||||
*
|
*
|
||||||
* also used as a placeholder to store source address for
|
* also used as a placeholder to store source address for
|
||||||
* a stateless socket */
|
* a stateless socket */
|
||||||
@ -267,6 +262,15 @@ struct stio_dev_sck_t
|
|||||||
* - connect() timeout for a connecting socket.
|
* - connect() timeout for a connecting socket.
|
||||||
* - SSL_accept() timeout for a socket accepting SSL */
|
* - SSL_accept() timeout for a socket accepting SSL */
|
||||||
stio_tmridx_t tmrjob_index;
|
stio_tmridx_t tmrjob_index;
|
||||||
|
|
||||||
|
/* connect timeout, ssl-connect timeout, ssl-accept timeout.
|
||||||
|
* it denotes timeout duration under some circumstances
|
||||||
|
* or an absolute expiry time under some other circumstances. */
|
||||||
|
stio_ntime_t tmout;
|
||||||
|
|
||||||
|
void* ssl_ctx;
|
||||||
|
void* ssl;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
@ -212,5 +212,23 @@ int stio_gettmrtmout (stio_t* stio, const stio_ntime_t* tm, stio_ntime_t* tmout)
|
|||||||
|
|
||||||
stio_tmrjob_t* stio_gettmrjob (stio_t* stio, stio_tmridx_t index)
|
stio_tmrjob_t* stio_gettmrjob (stio_t* stio, stio_tmridx_t index)
|
||||||
{
|
{
|
||||||
return (index < 0 || index >= stio->tmr.size)? STIO_NULL: &stio->tmr.jobs[index];
|
if (index < 0 || index >= stio->tmr.size)
|
||||||
|
{
|
||||||
|
stio->errnum = STIO_ENOENT;
|
||||||
|
return STIO_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return &stio->tmr.jobs[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
int stio_gettmrjobdeadline (stio_t* stio, stio_tmridx_t index, stio_ntime_t* deadline)
|
||||||
|
{
|
||||||
|
if (index < 0 || index >= stio->tmr.size)
|
||||||
|
{
|
||||||
|
stio->errnum = STIO_ENOENT;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*deadline = stio->tmr.jobs[index].when;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -120,8 +120,7 @@ enum stio_stopreq_t
|
|||||||
{
|
{
|
||||||
STIO_STOPREQ_NONE = 0,
|
STIO_STOPREQ_NONE = 0,
|
||||||
STIO_STOPREQ_TERMINATION,
|
STIO_STOPREQ_TERMINATION,
|
||||||
STIO_STOPREQ_WATCHER_UPDATE_ERROR,
|
STIO_STOPREQ_WATCHER_ERROR
|
||||||
STIO_STOPREQ_WATCHER_RENEW_ERROR
|
|
||||||
};
|
};
|
||||||
typedef enum stio_stopreq_t stio_stopreq_t;
|
typedef enum stio_stopreq_t stio_stopreq_t;
|
||||||
|
|
||||||
@ -577,6 +576,11 @@ STIO_EXPORT stio_tmrjob_t* stio_gettmrjob (
|
|||||||
stio_tmridx_t index
|
stio_tmridx_t index
|
||||||
);
|
);
|
||||||
|
|
||||||
|
STIO_EXPORT int stio_gettmrjobdeadline (
|
||||||
|
stio_t* stio,
|
||||||
|
stio_tmridx_t index,
|
||||||
|
stio_ntime_t* deadline
|
||||||
|
);
|
||||||
|
|
||||||
/* ========================================================================= */
|
/* ========================================================================= */
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user