Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit b0182c8

Browse files
committed
Issue #10075: Add a session_stats() method to SSLContext objects.
1 parent 0518842 commit b0182c8

4 files changed

Lines changed: 81 additions & 5 deletions

File tree

Doc/library/ssl.rst

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -481,13 +481,17 @@ SSL Contexts
481481

482482
.. versionadded:: 3.2
483483

484+
An SSL context holds various data longer-lived than single SSL connections,
485+
such as SSL configuration options, certificate(s) and private key(s).
486+
It also manages a cache of SSL sessions for server-side sockets, in order
487+
to speed up repeated connections from the same clients.
488+
484489
.. class:: SSLContext(protocol)
485490

486-
An object holding various data longer-lived than single SSL connections,
487-
such as SSL configuration options, certificate(s) and private key(s).
488-
You must pass *protocol* which must be one of the ``PROTOCOL_*`` constants
489-
defined in this module. :data:`PROTOCOL_SSLv23` is recommended for
490-
maximum interoperability.
491+
Create a new SSL context. You must pass *protocol* which must be one
492+
of the ``PROTOCOL_*`` constants defined in this module.
493+
:data:`PROTOCOL_SSLv23` is recommended for maximum interoperability.
494+
491495

492496
:class:`SSLContext` objects have the following methods and attributes:
493497

@@ -542,6 +546,18 @@ SSL Contexts
542546
and *suppress_ragged_eofs* have the same meaning as in the top-level
543547
:func:`wrap_socket` function.
544548

549+
.. method:: SSLContext.session_stats()
550+
551+
Get statistics about the SSL sessions created or managed by this context.
552+
A dictionary is returned which maps the names of each `piece of information
553+
<http://www.openssl.org/docs/ssl/SSL_CTX_sess_number.html>`_ to their
554+
numeric values. For example, here is the total number of hits and misses
555+
in the session cache since the context was created::
556+
557+
>>> stats = context.session_stats()
558+
>>> stats['hits'], stats['misses']
559+
(0, 0)
560+
545561
.. attribute:: SSLContext.options
546562

547563
An integer representing the set of SSL options enabled on this context.

Lib/test/test_ssl.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,23 @@ def test_load_verify_locations(self):
391391
ctx.load_verify_locations(CERTFILE, CAPATH)
392392
ctx.load_verify_locations(CERTFILE, capath=BYTES_CAPATH)
393393

394+
def test_session_stats(self):
395+
for proto in PROTOCOLS:
396+
ctx = ssl.SSLContext(proto)
397+
self.assertEqual(ctx.session_stats(), {
398+
'number': 0,
399+
'connect': 0,
400+
'connect_good': 0,
401+
'connect_renegotiate': 0,
402+
'accept': 0,
403+
'accept_good': 0,
404+
'accept_renegotiate': 0,
405+
'hits': 0,
406+
'misses': 0,
407+
'timeouts': 0,
408+
'cache_full': 0,
409+
})
410+
394411

395412
class NetworkedTests(unittest.TestCase):
396413

Misc/NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ Core and Builtins
1313
Library
1414
-------
1515

16+
- Issue #10075: Add a session_stats() method to SSLContext objects.
17+
1618
- Issue #9948: Fixed problem of losing filename case information.
1719

1820
Extensions

Modules/_ssl.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1716,6 +1716,45 @@ context_wrap_socket(PySSLContext *self, PyObject *args, PyObject *kwds)
17161716
return (PyObject *) newPySSLSocket(self->ctx, sock, server_side);
17171717
}
17181718

1719+
static PyObject *
1720+
session_stats(PySSLContext *self, PyObject *unused)
1721+
{
1722+
int r;
1723+
PyObject *value, *stats = PyDict_New();
1724+
if (!stats)
1725+
return NULL;
1726+
1727+
#define ADD_STATS(SSL_NAME, KEY_NAME) \
1728+
value = PyLong_FromLong(SSL_CTX_sess_ ## SSL_NAME (self->ctx)); \
1729+
if (value == NULL) \
1730+
goto error; \
1731+
r = PyDict_SetItemString(stats, KEY_NAME, value); \
1732+
Py_DECREF(value); \
1733+
if (r < 0) \
1734+
goto error;
1735+
1736+
ADD_STATS(number, "number");
1737+
ADD_STATS(connect, "connect");
1738+
ADD_STATS(connect_good, "connect_good");
1739+
ADD_STATS(connect_renegotiate, "connect_renegotiate");
1740+
ADD_STATS(accept, "accept");
1741+
ADD_STATS(accept_good, "accept_good");
1742+
ADD_STATS(accept_renegotiate, "accept_renegotiate");
1743+
ADD_STATS(accept, "accept");
1744+
ADD_STATS(hits, "hits");
1745+
ADD_STATS(misses, "misses");
1746+
ADD_STATS(timeouts, "timeouts");
1747+
ADD_STATS(cache_full, "cache_full");
1748+
1749+
#undef ADD_STATS
1750+
1751+
return stats;
1752+
1753+
error:
1754+
Py_DECREF(stats);
1755+
return NULL;
1756+
}
1757+
17191758
static PyGetSetDef context_getsetlist[] = {
17201759
{"options", (getter) get_options,
17211760
(setter) set_options, NULL},
@@ -1733,6 +1772,8 @@ static struct PyMethodDef context_methods[] = {
17331772
METH_VARARGS | METH_KEYWORDS, NULL},
17341773
{"load_verify_locations", (PyCFunction) load_verify_locations,
17351774
METH_VARARGS | METH_KEYWORDS, NULL},
1775+
{"session_stats", (PyCFunction) session_stats,
1776+
METH_NOARGS, NULL},
17361777
{NULL, NULL} /* sentinel */
17371778
};
17381779

0 commit comments

Comments
 (0)