Convert Context and Connection to real types
diff --git a/src/ssl/connection.c b/src/ssl/connection.c
index 2d309cd..a5fdc51 100755
--- a/src/ssl/connection.c
+++ b/src/ssl/connection.c
@@ -1107,24 +1107,25 @@
#undef ADD_ALIAS
#undef ADD_METHOD
+static char ssl_Connection_doc[] = "\n\
+Connection(context, socket) -> Connection instance\n\
+\n\
+Create a new Connection object, using the given OpenSSL.SSL.Context instance\n\
+and socket.\n\
+\n\
+@param context: An SSL Context to use for this connection\n\
+@param socket: The socket to use for transport layer\n\
+";
/*
- * Constructor for Connection objects
- *
- * Arguments: ctx - An SSL Context to use for this connection
- * sock - The socket to use for transport layer
- * Returns: The newly created Connection object
+ * Initializer used by ssl_Connection_new and ssl_Connection_New. *Not*
+ * tp_init. This takes an already allocated ssl_ConnectionObj, a context, and
+ * a optionally a socket, and glues them all together.
*/
-ssl_ConnectionObj *
-ssl_Connection_New(ssl_ContextObj *ctx, PyObject *sock)
-{
- ssl_ConnectionObj *self;
+static ssl_ConnectionObj*
+ssl_Connection_init(ssl_ConnectionObj *self, ssl_ContextObj *ctx, PyObject *sock) {
int fd;
- self = PyObject_GC_New(ssl_ConnectionObj, &ssl_Connection_Type);
- if (self == NULL)
- return NULL;
-
Py_INCREF(ctx);
self->context = ctx;
@@ -1166,9 +1167,6 @@
SSL_set_fd(self->ssl, (SOCKET_T)fd);
}
}
-
- PyObject_GC_Track(self);
-
return self;
error:
@@ -1179,6 +1177,49 @@
}
/*
+ * Constructor for Connection objects
+ *
+ * Arguments: ctx - An SSL Context to use for this connection
+ * sock - The socket to use for transport layer
+ * Returns: The newly created Connection object
+ */
+ssl_ConnectionObj *
+ssl_Connection_New(ssl_ContextObj *ctx, PyObject *sock) {
+ ssl_ConnectionObj *self;
+
+ self = PyObject_GC_New(ssl_ConnectionObj, &ssl_Connection_Type);
+ if (self == NULL) {
+ return NULL;
+ }
+ self = ssl_Connection_init(self, ctx, sock);
+ if (self == NULL) {
+ return NULL;
+ }
+ PyObject_GC_Track((PyObject *)self);
+ return self;
+}
+
+static PyObject*
+ssl_Connection_new(PyTypeObject *subtype, PyObject *args, PyObject *kwargs) {
+ ssl_ConnectionObj *self;
+ ssl_ContextObj *ctx;
+ PyObject *sock;
+ static char *kwlist[] = {"context", "socket", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!O:Connection", kwlist,
+ &ssl_Context_Type, &ctx, &sock)) {
+ return NULL;
+ }
+
+ self = (ssl_ConnectionObj *)subtype->tp_alloc(subtype, 1);
+ if (self == NULL) {
+ return NULL;
+ }
+
+ return (PyObject *)ssl_Connection_init(self, ctx, sock);
+}
+
+/*
* Find attribute
*
* Arguments: self - The Connection object
@@ -1265,12 +1306,12 @@
PyTypeObject ssl_Connection_Type = {
PyObject_HEAD_INIT(NULL)
0,
- "Connection",
+ "OpenSSL.SSL.Connection",
sizeof(ssl_ConnectionObj),
0,
(destructor)ssl_Connection_dealloc,
NULL, /* print */
- (getattrfunc)ssl_Connection_getattr,
+ (getattrfunc)ssl_Connection_getattr, /* tp_getattr */
NULL, /* setattr */
NULL, /* compare */
NULL, /* repr */
@@ -1284,25 +1325,47 @@
NULL, /* setattro */
NULL, /* as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
- NULL, /* doc */
+ ssl_Connection_doc, /* doc */
(traverseproc)ssl_Connection_traverse,
(inquiry)ssl_Connection_clear,
+ NULL, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ NULL, /* tp_iter */
+ NULL, /* tp_iternext */
+ ssl_Connection_methods, /* tp_methods */
+ NULL, /* tp_members */
+ NULL, /* tp_getset */
+ NULL, /* tp_base */
+ NULL, /* tp_dict */
+ NULL, /* tp_descr_get */
+ NULL, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ NULL, /* tp_init */
+ NULL, /* tp_alloc */
+ ssl_Connection_new, /* tp_new */
};
/*
* Initiailze the Connection part of the SSL sub module
*
- * Arguments: dict - Dictionary of the OpenSSL.SSL module
+ * Arguments: dict - The OpenSSL.SSL module
* Returns: 1 for success, 0 otherwise
*/
int
-init_ssl_connection(PyObject *dict)
-{
- ssl_Connection_Type.ob_type = &PyType_Type;
- Py_INCREF(&ssl_Connection_Type);
- if (PyDict_SetItemString(dict, "ConnectionType", (PyObject *)&ssl_Connection_Type) != 0)
+init_ssl_connection(PyObject *module) {
+
+ if (PyType_Ready(&ssl_Connection_Type) < 0) {
return 0;
+ }
+
+ if (PyModule_AddObject(module, "Connection", (PyObject *)&ssl_Connection_Type) != 0) {
+ return 0;
+ }
+
+ if (PyModule_AddObject(module, "ConnectionType", (PyObject *)&ssl_Connection_Type) != 0) {
+ return 0;
+ }
return 1;
}
diff --git a/src/ssl/context.c b/src/ssl/context.c
index c1e1934..cb9aa88 100644
--- a/src/ssl/context.c
+++ b/src/ssl/context.c
@@ -236,14 +236,22 @@
}
-
+static char ssl_Context_doc[] = "\n\
+Context(method) -> Context instance\n\
+\n\
+OpenSSL.SSL.Context instances define the parameters for setting up new SSL\n\
+connections.\n\
+\n\
+@param method: One of SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, or\n\
+ TLSv1_METHOD.\n\
+";
static char ssl_Context_load_verify_locations_doc[] = "\n\
Let SSL know where we can find trusted certificates for the certificate\n\
chain\n\
\n\
@param cafile: In which file we can find the certificates\n\
-@param capath: In which directory we can find the certificates\r\
+@param capath: In which directory we can find the certificates\n\
@return: None\n\
";
static PyObject *
@@ -963,38 +971,33 @@
};
#undef ADD_METHOD
-
-/* Constructor, takes an int specifying which method to use */
/*
- * Constructor for Context objects
- *
- * Arguments: i_method - The SSL method to use, one of the SSLv2_METHOD,
- * SSLv3_METHOD, SSLv23_METHOD and TLSv1_METHOD
- * constants.
- * Returns: The newly created Context object
+ * Despite the name which might suggest otherwise, this is not the tp_init for
+ * the Context type. It's just the common initialization code shared by the
+ * two _{Nn}ew functions below.
*/
-ssl_ContextObj *
-ssl_Context_New(int i_method)
-{
+static ssl_ContextObj*
+ssl_Context_init(ssl_ContextObj *self, int i_method) {
SSL_METHOD *method;
- ssl_ContextObj *self;
- switch (i_method)
- {
- /* Too bad TLSv1 servers can't accept SSLv3 clients */
- case ssl_SSLv2_METHOD: method = SSLv2_method(); break;
- case ssl_SSLv23_METHOD: method = SSLv23_method(); break;
- case ssl_SSLv3_METHOD: method = SSLv3_method(); break;
- case ssl_TLSv1_METHOD: method = TLSv1_method(); break;
+ switch (i_method) {
+ case ssl_SSLv2_METHOD:
+ method = SSLv2_method();
+ break;
+ case ssl_SSLv23_METHOD:
+ method = SSLv23_method();
+ break;
+ case ssl_SSLv3_METHOD:
+ method = SSLv3_method();
+ break;
+ case ssl_TLSv1_METHOD:
+ method = TLSv1_method();
+ break;
default:
PyErr_SetString(PyExc_ValueError, "No such protocol");
return NULL;
}
- self = PyObject_GC_New(ssl_ContextObj, &ssl_Context_Type);
- if (self == NULL)
- return (ssl_ContextObj *)PyErr_NoMemory();
-
self->ctx = SSL_CTX_new(method);
Py_INCREF(Py_None);
self->passphrase_callback = Py_None;
@@ -1016,23 +1019,46 @@
SSL_MODE_AUTO_RETRY);
self->tstate = NULL;
- PyObject_GC_Track((PyObject *)self);
return self;
}
/*
- * Find attribute
- *
- * Arguments: self - The Context object
- * name - The attribute name
- * Returns: A Python object for the attribute, or NULL if something went
- * wrong
+ * This one is exposed in the CObject API. I want to deprecate it.
*/
-static PyObject *
-ssl_Context_getattr(ssl_ContextObj *self, char *name)
-{
- return Py_FindMethod(ssl_Context_methods, (PyObject *)self, name);
+ssl_ContextObj*
+ssl_Context_New(int i_method) {
+ ssl_ContextObj *self;
+
+ self = PyObject_GC_New(ssl_ContextObj, &ssl_Context_Type);
+ if (self == NULL) {
+ return (ssl_ContextObj *)PyErr_NoMemory();
+ }
+ self = ssl_Context_init(self, i_method);
+ PyObject_GC_Track((PyObject *)self);
+ return self;
+}
+
+
+/*
+ * This one is the tp_new of the Context type. It's great.
+ */
+static PyObject*
+ssl_Context_new(PyTypeObject *subtype, PyObject *args, PyObject *kwargs) {
+ int i_method;
+ ssl_ContextObj *self;
+ static char *kwlist[] = {"method", NULL};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i:Context", kwlist, &i_method)) {
+ return NULL;
+ }
+
+ self = (ssl_ContextObj *)subtype->tp_alloc(subtype, 1);
+ if (self == NULL) {
+ return NULL;
+ }
+
+ return (PyObject *)ssl_Context_init(self, i_method);
}
/*
@@ -1103,12 +1129,12 @@
PyTypeObject ssl_Context_Type = {
PyObject_HEAD_INIT(NULL)
0,
- "Context",
+ "OpenSSL.SSL.Context",
sizeof(ssl_ContextObj),
0,
- (destructor)ssl_Context_dealloc,
+ (destructor)ssl_Context_dealloc, /* tp_dealloc */
NULL, /* print */
- (getattrfunc)ssl_Context_getattr,
+ NULL, /* tp_getattr */
NULL, /* setattr */
NULL, /* compare */
NULL, /* repr */
@@ -1121,26 +1147,48 @@
NULL, /* getattro */
NULL, /* setattro */
NULL, /* as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
- NULL, /* doc */
- (traverseproc)ssl_Context_traverse,
- (inquiry)ssl_Context_clear,
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ ssl_Context_doc, /* tp_doc */
+ (traverseproc)ssl_Context_traverse, /* tp_traverse */
+ (inquiry)ssl_Context_clear, /* tp_clear */
+ NULL, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ NULL, /* tp_iter */
+ NULL, /* tp_iternext */
+ ssl_Context_methods, /* tp_methods */
+ NULL, /* tp_members */
+ NULL, /* tp_getset */
+ NULL, /* tp_base */
+ NULL, /* tp_dict */
+ NULL, /* tp_descr_get */
+ NULL, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ NULL, /* tp_init */
+ NULL, /* tp_alloc */
+ ssl_Context_new, /* tp_new */
};
/*
* Initialize the Context part of the SSL sub module
*
- * Arguments: dict - Dictionary of the OpenSSL.SSL module
+ * Arguments: dict - The OpenSSL.SSL module
* Returns: 1 for success, 0 otherwise
*/
int
-init_ssl_context(PyObject *dict)
-{
- ssl_Context_Type.ob_type = &PyType_Type;
- Py_INCREF(&ssl_Context_Type);
- if (PyDict_SetItemString(dict, "ContextType", (PyObject *)&ssl_Context_Type) != 0)
+init_ssl_context(PyObject *module) {
+
+ if (PyType_Ready(&ssl_Context_Type) < 0) {
return 0;
+ }
+
+ if (PyModule_AddObject(module, "Context", (PyObject *)&ssl_Context_Type) < 0) {
+ return 0;
+ }
+
+ if (PyModule_AddObject(module, "ContextType", (PyObject *)&ssl_Context_Type) < 0) {
+ return 0;
+ }
return 1;
}
diff --git a/src/ssl/ssl.c b/src/ssl/ssl.c
index 2b8402d..94d4844 100644
--- a/src/ssl/ssl.c
+++ b/src/ssl/ssl.c
@@ -42,51 +42,9 @@
*ssl_WantX509LookupError, /* ... */
*ssl_SysCallError; /* Uses (errno,errstr) */
-static char ssl_Context_doc[] = "\n\
-The factory function inserted in the module dictionary to create Context\n\
-objects\n\
-\n\
-@param method: The SSL method to use\n\
-@return: The Context object\n\
-";
-
-static PyObject *
-ssl_Context(PyObject *spam, PyObject *args)
-{
- int method;
-
- if (!PyArg_ParseTuple(args, "i:Context", &method))
- return NULL;
-
- return (PyObject *)ssl_Context_New(method);
-}
-
-static char ssl_Connection_doc[] = "\n\
-The factory function inserted in the module dictionary to create Connection\n\
-objects\n\
-\n\
-@param ctx: An SSL Context to use for this connection\n\
-@param sock: The socket to use for transport layer\n\
-@return: The Connection object\n\
-";
-
-static PyObject *
-ssl_Connection(PyObject *spam, PyObject *args)
-{
- ssl_ContextObj *ctx;
- PyObject *sock;
-
- if (!PyArg_ParseTuple(args, "O!O:Connection", &ssl_Context_Type, &ctx, &sock))
- return NULL;
-
- return (PyObject *)ssl_Connection_New(ctx, sock);
-}
-
/* Methods in the OpenSSL.SSL module */
static PyMethodDef ssl_methods[] = {
- { "Context", ssl_Context, METH_VARARGS, ssl_Context_doc },
- { "Connection", ssl_Connection, METH_VARARGS, ssl_Connection_doc },
{ NULL, NULL }
};
@@ -101,15 +59,16 @@
{
static void *ssl_API[ssl_API_pointers];
PyObject *ssl_api_object;
- PyObject *module, *dict;
+ PyObject *module;
SSL_library_init();
ERR_load_SSL_strings();
import_crypto();
- if ((module = Py_InitModule3("SSL", ssl_methods, ssl_doc)) == NULL)
+ if ((module = Py_InitModule3("SSL", ssl_methods, ssl_doc)) == NULL) {
return;
+ }
/* Initialize the C API pointer array */
ssl_API[ssl_Context_New_NUM] = (void *)ssl_Context_New;
@@ -206,10 +165,9 @@
PyModule_AddIntConstant(module, "SENT_SHUTDOWN", SSL_SENT_SHUTDOWN);
PyModule_AddIntConstant(module, "RECEIVED_SHUTDOWN", SSL_RECEIVED_SHUTDOWN);
- dict = PyModule_GetDict(module);
- if (!init_ssl_context(dict))
+ if (!init_ssl_context(module))
goto error;
- if (!init_ssl_connection(dict))
+ if (!init_ssl_connection(module))
goto error;
#ifdef WITH_THREAD