kore

An easy to use, scalable and secure web application framework for writing web APIs in C.
Commits | Files | Refs | README | LICENSE | git clone https://git.kore.io/kore.git

python_methods.h (32950B)



      1 /*
      2  * Copyright (c) 2017-2022 Joris Vink <joris@coders.se>
      3  *
      4  * Permission to use, copy, modify, and distribute this software for any
      5  * purpose with or without fee is hereby granted, provided that the above
      6  * copyright notice and this permission notice appear in all copies.
      7  *
      8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     15  */
     16 
     17 #define CORO_STATE_RUNNABLE		1
     18 #define CORO_STATE_SUSPENDED		2
     19 
     20 struct python_coro {
     21 	u_int64_t			id;
     22 	int				state;
     23 	int				killed;
     24 	PyObject			*obj;
     25 	char				*name;
     26 	PyObject			*result;
     27 	struct pylock_op		*lockop;
     28 	struct pysocket_op		*sockop;
     29 	struct pygather_op		*gatherop;
     30 	struct http_request		*request;
     31 	PyObject			*exception;
     32 	char				*exception_msg;
     33 	TAILQ_ENTRY(python_coro)	list;
     34 };
     35 
     36 TAILQ_HEAD(coro_list, python_coro);
     37 
     38 static PyObject		*python_kore_app(PyObject *, PyObject *);
     39 static PyObject		*python_kore_log(PyObject *, PyObject *);
     40 static PyObject		*python_kore_time(PyObject *, PyObject *);
     41 static PyObject		*python_kore_lock(PyObject *, PyObject *);
     42 static PyObject		*python_kore_proc(PyObject *, PyObject *);
     43 static PyObject		*python_kore_fatal(PyObject *, PyObject *);
     44 static PyObject		*python_kore_queue(PyObject *, PyObject *);
     45 static PyObject		*python_kore_worker(PyObject *, PyObject *);
     46 static PyObject		*python_kore_tracer(PyObject *, PyObject *);
     47 static PyObject		*python_kore_fatalx(PyObject *, PyObject *);
     48 static PyObject		*python_kore_task_id(PyObject *, PyObject *);
     49 static PyObject		*python_kore_sigtrap(PyObject *, PyObject *);
     50 static PyObject		*python_kore_setname(PyObject *, PyObject *);
     51 static PyObject		*python_kore_suspend(PyObject *, PyObject *);
     52 static PyObject		*python_kore_shutdown(PyObject *, PyObject *);
     53 static PyObject		*python_kore_coroname(PyObject *, PyObject *);
     54 static PyObject		*python_kore_corotrace(PyObject *, PyObject *);
     55 static PyObject		*python_kore_task_kill(PyObject *, PyObject *);
     56 static PyObject		*python_kore_prerequest(PyObject *, PyObject *);
     57 static PyObject		*python_kore_task_create(PyObject *, PyObject *);
     58 static PyObject		*python_kore_socket_wrap(PyObject *, PyObject *);
     59 static PyObject		*python_kore_route(PyObject *, PyObject *, PyObject *);
     60 static PyObject		*python_kore_timer(PyObject *, PyObject *, PyObject *);
     61 static PyObject		*python_kore_domain(PyObject *, PyObject *, PyObject *);
     62 static PyObject		*python_kore_gather(PyObject *, PyObject *, PyObject *);
     63 static PyObject		*python_kore_sendobj(PyObject *, PyObject *,
     64 			    PyObject *);
     65 static PyObject		*python_kore_server(PyObject *, PyObject *,
     66 			    PyObject *);
     67 static PyObject		*python_kore_privsep(PyObject *, PyObject *,
     68 			    PyObject *);
     69 
     70 
     71 #if defined(KORE_USE_PGSQL)
     72 static PyObject		*python_kore_pgsql_query(PyObject *, PyObject *,
     73 			    PyObject *);
     74 static PyObject		*python_kore_pgsql_register(PyObject *, PyObject *);
     75 #endif
     76 
     77 #if defined(KORE_USE_CURL)
     78 static PyObject		*python_kore_curl_handle(PyObject *, PyObject *);
     79 static PyObject		*python_kore_httpclient(PyObject *,
     80 			    PyObject *, PyObject *);
     81 #endif
     82 
     83 static PyObject		*python_websocket_broadcast(PyObject *, PyObject *);
     84 
     85 #define METHOD(n, c, a)		{ n, (PyCFunction)c, a, NULL }
     86 #define GETTER(n, g)		{ n, (getter)g, NULL, NULL, NULL }
     87 #define SETTER(n, s)		{ n, NULL, (setter)s, NULL, NULL }
     88 #define GETSET(n, g, s)		{ n, (getter)g, (setter)s, NULL, NULL }
     89 
     90 static struct PyMethodDef pykore_methods[] = {
     91 	METHOD("app", python_kore_app, METH_VARARGS),
     92 	METHOD("log", python_kore_log, METH_VARARGS),
     93 	METHOD("time", python_kore_time, METH_NOARGS),
     94 	METHOD("lock", python_kore_lock, METH_NOARGS),
     95 	METHOD("proc", python_kore_proc, METH_VARARGS),
     96 	METHOD("queue", python_kore_queue, METH_VARARGS),
     97 	METHOD("worker", python_kore_worker, METH_VARARGS),
     98 	METHOD("tracer", python_kore_tracer, METH_VARARGS),
     99 	METHOD("fatal", python_kore_fatal, METH_VARARGS),
    100 	METHOD("fatalx", python_kore_fatalx, METH_VARARGS),
    101 	METHOD("task_id", python_kore_task_id, METH_NOARGS),
    102 	METHOD("sigtrap", python_kore_sigtrap, METH_VARARGS),
    103 	METHOD("setname", python_kore_setname, METH_VARARGS),
    104 	METHOD("suspend", python_kore_suspend, METH_VARARGS),
    105 	METHOD("shutdown", python_kore_shutdown, METH_NOARGS),
    106 	METHOD("coroname", python_kore_coroname, METH_VARARGS),
    107 	METHOD("corotrace", python_kore_corotrace, METH_VARARGS),
    108 	METHOD("task_kill", python_kore_task_kill, METH_VARARGS),
    109 	METHOD("prerequest", python_kore_prerequest, METH_VARARGS),
    110 	METHOD("task_create", python_kore_task_create, METH_VARARGS),
    111 	METHOD("socket_wrap", python_kore_socket_wrap, METH_VARARGS),
    112 	METHOD("route", python_kore_route, METH_VARARGS | METH_KEYWORDS),
    113 	METHOD("timer", python_kore_timer, METH_VARARGS | METH_KEYWORDS),
    114 	METHOD("domain", python_kore_domain, METH_VARARGS | METH_KEYWORDS),
    115 	METHOD("server", python_kore_server, METH_VARARGS | METH_KEYWORDS),
    116 	METHOD("gather", python_kore_gather, METH_VARARGS | METH_KEYWORDS),
    117 	METHOD("privsep", python_kore_privsep, METH_VARARGS | METH_KEYWORDS),
    118 	METHOD("sendobj", python_kore_sendobj, METH_VARARGS | METH_KEYWORDS),
    119 	METHOD("websocket_broadcast", python_websocket_broadcast, METH_VARARGS),
    120 #if defined(KORE_USE_PGSQL)
    121 	METHOD("dbsetup", python_kore_pgsql_register, METH_VARARGS),
    122 	METHOD("dbquery", python_kore_pgsql_query,
    123 	    METH_VARARGS | METH_KEYWORDS),
    124 #endif
    125 #if defined(KORE_USE_CURL)
    126 	METHOD("curl", python_kore_curl_handle, METH_VARARGS),
    127 	METHOD("httpclient", python_kore_httpclient,
    128 	    METH_VARARGS | METH_KEYWORDS),
    129 #endif
    130 	{ NULL, NULL, 0, NULL }
    131 };
    132 
    133 static struct PyModuleDef pykore_module = {
    134 	PyModuleDef_HEAD_INIT, "kore", NULL, -1, pykore_methods
    135 };
    136 
    137 struct pyconfig {
    138 	PyObject_HEAD
    139 };
    140 
    141 static int	pyconfig_setattr(PyObject *, PyObject *, PyObject *);
    142 
    143 static PyTypeObject pyconfig_type = {
    144 	PyVarObject_HEAD_INIT(NULL, 0)
    145 	.tp_name = "kore.config",
    146 	.tp_doc = "kore configuration",
    147 	.tp_setattro = pyconfig_setattr,
    148 	.tp_basicsize = sizeof(struct pyconfig),
    149 	.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
    150 };
    151 
    152 #if defined(__linux__)
    153 struct pyseccomp {
    154 	PyObject_HEAD
    155 	size_t			elm;
    156 	u_int8_t		*filters;
    157 };
    158 
    159 static PyObject	*pyseccomp_allow(struct pyseccomp *, PyObject *);
    160 static PyObject	*pyseccomp_allow_arg(struct pyseccomp *, PyObject *);
    161 static PyObject	*pyseccomp_allow_flag(struct pyseccomp *, PyObject *);
    162 static PyObject	*pyseccomp_allow_mask(struct pyseccomp *, PyObject *);
    163 
    164 static PyObject	*pyseccomp_deny(struct pyseccomp *, PyObject *, PyObject *);
    165 static PyObject	*pyseccomp_deny_arg(struct pyseccomp *, PyObject *, PyObject *);
    166 static PyObject	*pyseccomp_deny_flag(struct pyseccomp *,
    167 		    PyObject *, PyObject *);
    168 static PyObject	*pyseccomp_deny_mask(struct pyseccomp *,
    169 		    PyObject *, PyObject *);
    170 
    171 static PyObject	*pyseccomp_bpf_stmt(struct pyseccomp *, PyObject *);
    172 
    173 static PyMethodDef pyseccomp_methods[] = {
    174 	METHOD("allow", pyseccomp_allow, METH_VARARGS),
    175 	METHOD("bpf_stmt", pyseccomp_bpf_stmt, METH_VARARGS),
    176 	METHOD("allow_arg", pyseccomp_allow_arg, METH_VARARGS),
    177 	METHOD("allow_flag", pyseccomp_allow_flag, METH_VARARGS),
    178 	METHOD("allow_mask", pyseccomp_allow_mask, METH_VARARGS),
    179 	METHOD("deny", pyseccomp_deny, METH_VARARGS | METH_KEYWORDS),
    180 	METHOD("deny_arg", pyseccomp_deny_arg, METH_VARARGS | METH_KEYWORDS),
    181 	METHOD("deny_flag", pyseccomp_deny_flag, METH_VARARGS | METH_KEYWORDS),
    182 	METHOD("deny_mask", pyseccomp_deny_mask, METH_VARARGS | METH_KEYWORDS),
    183 	METHOD(NULL, NULL, -1)
    184 };
    185 
    186 static void	pyseccomp_dealloc(struct pyseccomp *);
    187 
    188 static PyTypeObject pyseccomp_type = {
    189 	PyVarObject_HEAD_INIT(NULL, 0)
    190 	.tp_name = "kore.seccomp",
    191 	.tp_doc = "kore seccomp configuration",
    192 	.tp_methods = pyseccomp_methods,
    193 	.tp_basicsize = sizeof(struct pyseccomp),
    194 	.tp_dealloc = (destructor)pyseccomp_dealloc,
    195 	.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
    196 };
    197 #endif
    198 
    199 struct pyroute {
    200 	PyObject_HEAD
    201 	char			*path;
    202 	PyObject		*func;
    203 	PyObject		*kwargs;
    204 	struct kore_domain	*domain;
    205 	TAILQ_ENTRY(pyroute)	list;
    206 };
    207 
    208 static PyObject	*pyroute_inner(struct pyroute *, PyObject *);
    209 static void	pyroute_dealloc(struct pyroute *);
    210 
    211 static PyMethodDef pyroute_methods[] = {
    212 	METHOD("inner", pyroute_inner, METH_VARARGS),
    213 	METHOD(NULL, NULL, -1)
    214 };
    215 
    216 static PyTypeObject pyroute_type = {
    217 	PyVarObject_HEAD_INIT(NULL, 0)
    218 	.tp_name = "kore.route",
    219 	.tp_doc = "kore route function",
    220 	.tp_methods = pyroute_methods,
    221 	.tp_basicsize = sizeof(struct pyroute),
    222 	.tp_dealloc = (destructor)pyroute_dealloc,
    223 	.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
    224 };
    225 
    226 struct pydomain {
    227 	PyObject_HEAD
    228 	struct kore_domain		*config;
    229 	struct kore_module_handle	*next;
    230 	PyObject			*kwargs;
    231 };
    232 
    233 static PyObject	*pydomain_filemaps(struct pydomain *, PyObject *);
    234 static PyObject	*pydomain_route(struct pydomain *, PyObject *, PyObject *);
    235 
    236 static PyMethodDef pydomain_methods[] = {
    237 	METHOD("filemaps", pydomain_filemaps, METH_VARARGS),
    238 	METHOD("route", pydomain_route, METH_VARARGS | METH_KEYWORDS),
    239 	METHOD(NULL, NULL, -1)
    240 };
    241 
    242 static int	pydomain_set_accesslog(struct pydomain *, PyObject *, void *);
    243 
    244 static PyGetSetDef pydomain_getset[] = {
    245 	SETTER("accesslog", pydomain_set_accesslog),
    246 	SETTER(NULL, NULL),
    247 };
    248 
    249 static void	pydomain_dealloc(struct pydomain *);
    250 
    251 static PyTypeObject pydomain_type = {
    252 	PyVarObject_HEAD_INIT(NULL, 0)
    253 	.tp_name = "kore.domain",
    254 	.tp_doc = "kore domain configuration",
    255 	.tp_getset = pydomain_getset,
    256 	.tp_methods = pydomain_methods,
    257 	.tp_basicsize = sizeof(struct pydomain),
    258 	.tp_dealloc = (destructor)pydomain_dealloc,
    259 	.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
    260 };
    261 
    262 #define PYSUSPEND_OP_INIT	1
    263 #define PYSUSPEND_OP_WAIT	2
    264 #define PYSUSPEND_OP_CONTINUE	3
    265 
    266 struct pysuspend_op {
    267 	PyObject_HEAD
    268 	int			state;
    269 	int			delay;
    270 	struct python_coro	*coro;
    271 	struct kore_timer	*timer;
    272 };
    273 
    274 static void	pysuspend_op_dealloc(struct pysuspend_op *);
    275 
    276 static PyObject	*pysuspend_op_await(PyObject *);
    277 static PyObject	*pysuspend_op_iternext(struct pysuspend_op *);
    278 
    279 static PyAsyncMethods pysuspend_op_async = {
    280 	(unaryfunc)pysuspend_op_await,
    281 	NULL,
    282 	NULL
    283 };
    284 
    285 static PyTypeObject pysuspend_op_type = {
    286 	PyVarObject_HEAD_INIT(NULL, 0)
    287 	.tp_name = "kore.suspend",
    288 	.tp_doc = "suspension operation",
    289 	.tp_as_async = &pysuspend_op_async,
    290 	.tp_iternext = (iternextfunc)pysuspend_op_iternext,
    291 	.tp_basicsize = sizeof(struct pysuspend_op),
    292 	.tp_dealloc = (destructor)pysuspend_op_dealloc,
    293 	.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
    294 };
    295 
    296 struct pytimer {
    297 	PyObject_HEAD
    298 	int			flags;
    299 	struct kore_timer	*run;
    300 	PyObject		*callable;
    301 	PyObject		*udata;
    302 };
    303 
    304 static PyObject	*pytimer_close(struct pytimer *, PyObject *);
    305 
    306 static PyMethodDef pytimer_methods[] = {
    307 	METHOD("close", pytimer_close, METH_NOARGS),
    308 	METHOD(NULL, NULL, -1)
    309 };
    310 
    311 static void	pytimer_dealloc(struct pytimer *);
    312 
    313 static PyTypeObject pytimer_type = {
    314 	PyVarObject_HEAD_INIT(NULL, 0)
    315 	.tp_name = "kore.timer",
    316 	.tp_doc = "kore timer implementation",
    317 	.tp_methods = pytimer_methods,
    318 	.tp_basicsize = sizeof(struct pytimer),
    319 	.tp_dealloc = (destructor)pytimer_dealloc,
    320 	.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
    321 };
    322 
    323 /* XXX */
    324 struct pysocket;
    325 struct pysocket_op;
    326 
    327 struct pysocket_event {
    328 	struct kore_event	evt;
    329 	struct pysocket		*s;
    330 };
    331 
    332 struct pysocket {
    333 	PyObject_HEAD
    334 	int			fd;
    335 	int			family;
    336 	int			protocol;
    337 	int			scheduled;
    338 	PyObject		*socket;
    339 	socklen_t		addr_len;
    340 
    341 	struct pysocket_event	event;
    342 	struct pysocket_op	*recvop;
    343 	struct pysocket_op	*sendop;
    344 
    345 	union {
    346 		struct sockaddr_in	ipv4;
    347 		struct sockaddr_un	sun;
    348 	} addr;
    349 };
    350 
    351 static PyObject *pysocket_send(struct pysocket *, PyObject *);
    352 static PyObject *pysocket_recv(struct pysocket *, PyObject *);
    353 static PyObject *pysocket_close(struct pysocket *, PyObject *);
    354 static PyObject *pysocket_accept(struct pysocket *, PyObject *);
    355 static PyObject *pysocket_sendto(struct pysocket *, PyObject *);
    356 static PyObject *pysocket_connect(struct pysocket *, PyObject *);
    357 static PyObject *pysocket_recvmsg(struct pysocket *, PyObject *);
    358 static PyObject *pysocket_recvfrom(struct pysocket *, PyObject *);
    359 
    360 static PyMethodDef pysocket_methods[] = {
    361 	METHOD("recv", pysocket_recv, METH_VARARGS),
    362 	METHOD("send", pysocket_send, METH_VARARGS),
    363 	METHOD("close", pysocket_close, METH_NOARGS),
    364 	METHOD("accept", pysocket_accept, METH_NOARGS),
    365 	METHOD("sendto", pysocket_sendto, METH_VARARGS),
    366 	METHOD("connect", pysocket_connect, METH_VARARGS),
    367 	METHOD("recvmsg", pysocket_recvmsg, METH_VARARGS),
    368 	METHOD("recvfrom", pysocket_recvfrom, METH_VARARGS),
    369 	METHOD(NULL, NULL, -1),
    370 };
    371 
    372 static void	pysocket_dealloc(struct pysocket *);
    373 
    374 static PyTypeObject pysocket_type = {
    375 	PyVarObject_HEAD_INIT(NULL, 0)
    376 	.tp_name = "kore.socket",
    377 	.tp_doc = "kore socket implementation",
    378 	.tp_methods = pysocket_methods,
    379 	.tp_basicsize = sizeof(struct pysocket),
    380 	.tp_dealloc = (destructor)pysocket_dealloc,
    381 	.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
    382 };
    383 
    384 #define PYSOCKET_TYPE_ACCEPT	1
    385 #define PYSOCKET_TYPE_CONNECT	2
    386 #define PYSOCKET_TYPE_RECV	3
    387 #define PYSOCKET_TYPE_SEND	4
    388 #define PYSOCKET_TYPE_RECVFROM	5
    389 #define PYSOCKET_TYPE_SENDTO	6
    390 #define PYSOCKET_TYPE_RECVMSG	7
    391 
    392 struct pysocket_op {
    393 	PyObject_HEAD
    394 	int				eof;
    395 	int				type;
    396 	void				*self;
    397 	struct python_coro		*coro;
    398 	int				state;
    399 	size_t				length;
    400 	struct kore_buf			buffer;
    401 	struct pysocket			*socket;
    402 	struct kore_timer		*timer;
    403 
    404 	union {
    405 		struct sockaddr_in	ipv4;
    406 		struct sockaddr_un	sun;
    407 	} sendaddr;
    408 };
    409 
    410 static void	pysocket_op_dealloc(struct pysocket_op *);
    411 
    412 static PyObject	*pysocket_op_await(PyObject *);
    413 static PyObject	*pysocket_op_iternext(struct pysocket_op *);
    414 
    415 static PyAsyncMethods pysocket_op_async = {
    416 	(unaryfunc)pysocket_op_await,
    417 	NULL,
    418 	NULL
    419 };
    420 
    421 static PyTypeObject pysocket_op_type = {
    422 	PyVarObject_HEAD_INIT(NULL, 0)
    423 	.tp_name = "kore.socketop",
    424 	.tp_doc = "socket operation",
    425 	.tp_as_async = &pysocket_op_async,
    426 	.tp_iternext = (iternextfunc)pysocket_op_iternext,
    427 	.tp_basicsize = sizeof(struct pysocket_op),
    428 	.tp_dealloc = (destructor)pysocket_op_dealloc,
    429 	.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
    430 };
    431 
    432 struct pyqueue_waiting {
    433 	struct python_coro		*coro;
    434 	struct pyqueue_op		*op;
    435 	TAILQ_ENTRY(pyqueue_waiting)	list;
    436 };
    437 
    438 struct pyqueue_object {
    439 	PyObject			*obj;
    440 	TAILQ_ENTRY(pyqueue_object)	list;
    441 };
    442 
    443 struct pyqueue {
    444 	PyObject_HEAD
    445 	TAILQ_HEAD(, pyqueue_object)	objects;
    446 	TAILQ_HEAD(, pyqueue_waiting)	waiting;
    447 };
    448 
    449 static PyObject *pyqueue_pop(struct pyqueue *, PyObject *);
    450 static PyObject *pyqueue_push(struct pyqueue *, PyObject *);
    451 static PyObject *pyqueue_popnow(struct pyqueue *, PyObject *);
    452 
    453 static PyMethodDef pyqueue_methods[] = {
    454 	METHOD("pop", pyqueue_pop, METH_NOARGS),
    455 	METHOD("push", pyqueue_push, METH_VARARGS),
    456 	METHOD("popnow", pyqueue_popnow, METH_NOARGS),
    457 	METHOD(NULL, NULL, -1)
    458 };
    459 
    460 static void	pyqueue_dealloc(struct pyqueue *);
    461 
    462 static PyTypeObject pyqueue_type = {
    463 	PyVarObject_HEAD_INIT(NULL, 0)
    464 	.tp_name = "kore.queue",
    465 	.tp_doc = "queue",
    466 	.tp_methods = pyqueue_methods,
    467 	.tp_basicsize = sizeof(struct pyqueue),
    468 	.tp_dealloc = (destructor)pyqueue_dealloc,
    469 	.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
    470 };
    471 
    472 struct pyqueue_op {
    473 	PyObject_HEAD
    474 	struct pyqueue		*queue;
    475 	struct pyqueue_waiting	*waiting;
    476 };
    477 
    478 static void	pyqueue_op_dealloc(struct pyqueue_op *);
    479 
    480 static PyObject	*pyqueue_op_await(PyObject *);
    481 static PyObject	*pyqueue_op_iternext(struct pyqueue_op *);
    482 
    483 static PyAsyncMethods pyqueue_op_async = {
    484 	(unaryfunc)pyqueue_op_await,
    485 	NULL,
    486 	NULL
    487 };
    488 
    489 static PyTypeObject pyqueue_op_type = {
    490 	PyVarObject_HEAD_INIT(NULL, 0)
    491 	.tp_name = "kore.queueop",
    492 	.tp_doc = "queue waitable",
    493 	.tp_as_async = &pyqueue_op_async,
    494 	.tp_iternext = (iternextfunc)pyqueue_op_iternext,
    495 	.tp_basicsize = sizeof(struct pyqueue_op),
    496 	.tp_dealloc = (destructor)pyqueue_op_dealloc,
    497 	.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
    498 };
    499 
    500 struct pylock {
    501 	PyObject_HEAD
    502 	struct python_coro		*owner;
    503 	TAILQ_HEAD(, pylock_op)		ops;
    504 };
    505 
    506 static PyObject *pylock_aexit(struct pylock *, PyObject *);
    507 static PyObject *pylock_aenter(struct pylock *, PyObject *);
    508 static PyObject *pylock_release(struct pylock *, PyObject *);
    509 static PyObject *pylock_trylock(struct pylock *, PyObject *);
    510 
    511 static PyMethodDef pylock_methods[] = {
    512 	METHOD("acquire", pylock_aenter, METH_NOARGS),
    513 	METHOD("release", pylock_release, METH_NOARGS),
    514 	METHOD("trylock", pylock_trylock, METH_NOARGS),
    515 	METHOD("__aexit__", pylock_aexit, METH_VARARGS),
    516 	METHOD("__aenter__", pylock_aenter, METH_NOARGS),
    517 	METHOD(NULL, NULL, -1)
    518 };
    519 
    520 static void	pylock_dealloc(struct pylock *);
    521 
    522 static PyTypeObject pylock_type = {
    523 	PyVarObject_HEAD_INIT(NULL, 0)
    524 	.tp_name = "kore.lock",
    525 	.tp_doc = "locking mechanism",
    526 	.tp_methods = pylock_methods,
    527 	.tp_basicsize = sizeof(struct pylock),
    528 	.tp_dealloc = (destructor)pylock_dealloc,
    529 	.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
    530 };
    531 
    532 struct pylock_op {
    533 	PyObject_HEAD
    534 	int			locking;
    535 	int			active;
    536 	struct pylock		*lock;
    537 	struct python_coro	*coro;
    538 	TAILQ_ENTRY(pylock_op)	list;
    539 };
    540 
    541 static void	pylock_op_dealloc(struct pylock_op *);
    542 
    543 static PyObject	*pylock_op_await(PyObject *);
    544 static PyObject	*pylock_op_iternext(struct pylock_op *);
    545 
    546 static PyAsyncMethods pylock_op_async = {
    547 	(unaryfunc)pylock_op_await,
    548 	NULL,
    549 	NULL
    550 };
    551 
    552 static PyTypeObject pylock_op_type = {
    553 	PyVarObject_HEAD_INIT(NULL, 0)
    554 	.tp_name = "kore.lockop",
    555 	.tp_doc = "lock awaitable",
    556 	.tp_as_async = &pylock_op_async,
    557 	.tp_iternext = (iternextfunc)pylock_op_iternext,
    558 	.tp_basicsize = sizeof(struct pylock_op),
    559 	.tp_dealloc = (destructor)pylock_op_dealloc,
    560 	.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
    561 };
    562 
    563 struct pyproc {
    564 	PyObject_HEAD
    565 	pid_t			pid;
    566 	pid_t			apid;
    567 	int			reaped;
    568 	int			status;
    569 	struct pyproc_op	*op;
    570 	struct pysocket		*in;
    571 	struct pysocket		*out;
    572 	struct python_coro	*coro;
    573 	struct kore_timer	*timer;
    574 	TAILQ_ENTRY(pyproc)	list;
    575 };
    576 
    577 static void	pyproc_dealloc(struct pyproc *);
    578 
    579 static PyObject	*pyproc_kill(struct pyproc *, PyObject *);
    580 static PyObject	*pyproc_reap(struct pyproc *, PyObject *);
    581 static PyObject	*pyproc_recv(struct pyproc *, PyObject *);
    582 static PyObject	*pyproc_send(struct pyproc *, PyObject *);
    583 static PyObject	*pyproc_close_stdin(struct pyproc *, PyObject *);
    584 
    585 static PyMethodDef pyproc_methods[] = {
    586 	METHOD("kill", pyproc_kill, METH_NOARGS),
    587 	METHOD("reap", pyproc_reap, METH_NOARGS),
    588 	METHOD("recv", pyproc_recv, METH_VARARGS),
    589 	METHOD("send", pyproc_send, METH_VARARGS),
    590 	METHOD("close_stdin", pyproc_close_stdin, METH_NOARGS),
    591 	METHOD(NULL, NULL, -1),
    592 };
    593 
    594 static PyObject	*pyproc_get_pid(struct pyproc *, void *);
    595 
    596 static PyGetSetDef pyproc_getset[] = {
    597 	GETTER("pid", pyproc_get_pid),
    598 	GETTER(NULL, NULL),
    599 };
    600 
    601 static PyTypeObject pyproc_type = {
    602 	PyVarObject_HEAD_INIT(NULL, 0)
    603 	.tp_name = "kore.proc",
    604 	.tp_doc = "async process",
    605 	.tp_getset = pyproc_getset,
    606 	.tp_methods = pyproc_methods,
    607 	.tp_basicsize = sizeof(struct pyproc),
    608 	.tp_dealloc = (destructor)pyproc_dealloc,
    609 	.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
    610 };
    611 
    612 struct pyproc_op {
    613 	PyObject_HEAD
    614 	struct pyproc		*proc;
    615 	struct python_coro	*coro;
    616 };
    617 
    618 static void	pyproc_op_dealloc(struct pyproc_op *);
    619 
    620 static PyObject	*pyproc_op_await(PyObject *);
    621 static PyObject	*pyproc_op_iternext(struct pyproc_op *);
    622 
    623 static PyAsyncMethods pyproc_op_async = {
    624 	(unaryfunc)pyproc_op_await,
    625 	NULL,
    626 	NULL
    627 };
    628 
    629 static PyTypeObject pyproc_op_type = {
    630 	PyVarObject_HEAD_INIT(NULL, 0)
    631 	.tp_name = "kore.proc_op",
    632 	.tp_doc = "proc reaper awaitable",
    633 	.tp_as_async = &pyproc_op_async,
    634 	.tp_iternext = (iternextfunc)pyproc_op_iternext,
    635 	.tp_basicsize = sizeof(struct pyproc_op),
    636 	.tp_dealloc = (destructor)pyproc_op_dealloc,
    637 	.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
    638 };
    639 
    640 struct pygather_coro {
    641 	struct python_coro		*coro;
    642 	PyObject			*result;
    643 	TAILQ_ENTRY(pygather_coro)	list;
    644 };
    645 
    646 struct pygather_result {
    647 	PyObject			*obj;
    648 	TAILQ_ENTRY(pygather_result)	list;
    649 };
    650 
    651 struct pygather_op {
    652 	PyObject_HEAD
    653 	int				count;
    654 	int				running;
    655 	int				concurrency;
    656 	struct python_coro		*coro;
    657 	TAILQ_HEAD(, pygather_result)	results;
    658 	TAILQ_HEAD(, pygather_coro)	coroutines;
    659 };
    660 
    661 static void	pygather_op_dealloc(struct pygather_op *);
    662 
    663 static PyObject	*pygather_op_await(PyObject *);
    664 static PyObject	*pygather_op_iternext(struct pygather_op *);
    665 
    666 static PyAsyncMethods pygather_op_async = {
    667 	(unaryfunc)pygather_op_await,
    668 	NULL,
    669 	NULL
    670 };
    671 
    672 static PyTypeObject pygather_op_type = {
    673 	PyVarObject_HEAD_INIT(NULL, 0)
    674 	.tp_name = "kore.pygather_op",
    675 	.tp_doc = "coroutine gathering",
    676 	.tp_as_async = &pygather_op_async,
    677 	.tp_iternext = (iternextfunc)pygather_op_iternext,
    678 	.tp_basicsize = sizeof(struct pygather_op),
    679 	.tp_dealloc = (destructor)pygather_op_dealloc,
    680 	.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
    681 };
    682 
    683 struct pyconnection {
    684 	PyObject_HEAD
    685 	struct connection	*c;
    686 };
    687 
    688 static PyObject *pyconnection_disconnect(struct pyconnection *, PyObject *);
    689 static PyObject *pyconnection_websocket_send(struct pyconnection *, PyObject *);
    690 
    691 static PyMethodDef pyconnection_methods[] = {
    692 	METHOD("disconnect", pyconnection_disconnect, METH_NOARGS),
    693 	METHOD("websocket_send", pyconnection_websocket_send, METH_VARARGS),
    694 	METHOD(NULL, NULL, -1),
    695 };
    696 
    697 static PyObject	*pyconnection_get_fd(struct pyconnection *, void *);
    698 static PyObject	*pyconnection_get_addr(struct pyconnection *, void *);
    699 
    700 static PyObject	*pyconnection_get_peer_x509(struct pyconnection *, void *);
    701 static PyObject	*pyconnection_get_peer_x509dict(struct pyconnection *, void *);
    702 
    703 static PyGetSetDef pyconnection_getset[] = {
    704 	GETTER("fd", pyconnection_get_fd),
    705 	GETTER("addr", pyconnection_get_addr),
    706 	GETTER("x509", pyconnection_get_peer_x509),
    707 	GETTER("x509dict", pyconnection_get_peer_x509dict),
    708 	GETTER(NULL, NULL),
    709 };
    710 
    711 static void	pyconnection_dealloc(struct pyconnection *);
    712 
    713 static PyTypeObject pyconnection_type = {
    714 	PyVarObject_HEAD_INIT(NULL, 0)
    715 	.tp_name = "kore.connection",
    716 	.tp_doc = "struct connection",
    717 	.tp_getset = pyconnection_getset,
    718 	.tp_methods = pyconnection_methods,
    719 	.tp_basicsize = sizeof(struct pyconnection),
    720 	.tp_dealloc = (destructor)pyconnection_dealloc,
    721 	.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
    722 };
    723 
    724 #define PYHTTP_STATE_INIT		0
    725 #define PYHTTP_STATE_PREPROCESS		1
    726 #define PYHTTP_STATE_RUN		2
    727 
    728 struct pyhttp_request {
    729 	PyObject_HEAD
    730 	struct http_request	*req;
    731 	PyObject		*dict;
    732 	PyObject		*data;
    733 };
    734 
    735 struct pyhttp_iterobj {
    736 	int			remove;
    737 	PyObject		*iterator;
    738 	struct connection	*connection;
    739 	struct kore_buf		buf;
    740 };
    741 
    742 struct pyhttp_file {
    743 	PyObject_HEAD
    744 	struct http_file	*file;
    745 };
    746 
    747 static void	pyhttp_dealloc(struct pyhttp_request *);
    748 static void	pyhttp_file_dealloc(struct pyhttp_file *);
    749 
    750 static PyObject *pyhttp_cookie(struct pyhttp_request *, PyObject *);
    751 static PyObject	*pyhttp_response(struct pyhttp_request *, PyObject *);
    752 static PyObject *pyhttp_argument(struct pyhttp_request *, PyObject *);
    753 static PyObject	*pyhttp_body_read(struct pyhttp_request *, PyObject *);
    754 static PyObject	*pyhttp_file_lookup(struct pyhttp_request *, PyObject *);
    755 static PyObject	*pyhttp_populate_get(struct pyhttp_request *, PyObject *);
    756 static PyObject	*pyhttp_populate_post(struct pyhttp_request *, PyObject *);
    757 static PyObject	*pyhttp_populate_multi(struct pyhttp_request *, PyObject *);
    758 static PyObject	*pyhttp_populate_cookies(struct pyhttp_request *, PyObject *);
    759 static PyObject	*pyhttp_request_header(struct pyhttp_request *, PyObject *);
    760 static PyObject	*pyhttp_response_header(struct pyhttp_request *, PyObject *);
    761 static PyObject *pyhttp_websocket_handshake(struct pyhttp_request *,
    762 		    PyObject *);
    763 
    764 static PyMethodDef pyhttp_request_methods[] = {
    765 	METHOD("cookie", pyhttp_cookie, METH_VARARGS),
    766 	METHOD("response", pyhttp_response, METH_VARARGS),
    767 	METHOD("argument", pyhttp_argument, METH_VARARGS),
    768 	METHOD("body_read", pyhttp_body_read, METH_VARARGS),
    769 	METHOD("file_lookup", pyhttp_file_lookup, METH_VARARGS),
    770 	METHOD("populate_get", pyhttp_populate_get, METH_NOARGS),
    771 	METHOD("populate_post", pyhttp_populate_post, METH_NOARGS),
    772 	METHOD("populate_multi", pyhttp_populate_multi, METH_NOARGS),
    773 	METHOD("populate_cookies", pyhttp_populate_cookies, METH_NOARGS),
    774 	METHOD("request_header", pyhttp_request_header, METH_VARARGS),
    775 	METHOD("response_header", pyhttp_response_header, METH_VARARGS),
    776 	METHOD("websocket_handshake", pyhttp_websocket_handshake, METH_VARARGS),
    777 	METHOD(NULL, NULL, -1)
    778 };
    779 
    780 static PyObject	*pyhttp_get_host(struct pyhttp_request *, void *);
    781 static PyObject	*pyhttp_get_path(struct pyhttp_request *, void *);
    782 static PyObject	*pyhttp_get_body(struct pyhttp_request *, void *);
    783 static PyObject	*pyhttp_get_agent(struct pyhttp_request *, void *);
    784 static PyObject	*pyhttp_get_method(struct pyhttp_request *, void *);
    785 static PyObject	*pyhttp_get_protocol(struct pyhttp_request *, void *);
    786 static PyObject	*pyhttp_get_body_path(struct pyhttp_request *, void *);
    787 static PyObject	*pyhttp_get_connection(struct pyhttp_request *, void *);
    788 static PyObject	*pyhttp_get_body_digest(struct pyhttp_request *, void *);
    789 
    790 static PyGetSetDef pyhttp_request_getset[] = {
    791 	GETTER("host", pyhttp_get_host),
    792 	GETTER("path", pyhttp_get_path),
    793 	GETTER("body", pyhttp_get_body),
    794 	GETTER("agent", pyhttp_get_agent),
    795 	GETTER("method", pyhttp_get_method),
    796 	GETTER("protocol", pyhttp_get_protocol),
    797 	GETTER("body_path", pyhttp_get_body_path),
    798 	GETTER("body_digest", pyhttp_get_body_digest),
    799 	GETTER("connection", pyhttp_get_connection),
    800 	GETTER(NULL, NULL)
    801 };
    802 
    803 static PyTypeObject pyhttp_request_type = {
    804 	PyVarObject_HEAD_INIT(NULL, 0)
    805 	.tp_name = "kore.http_request",
    806 	.tp_doc = "struct http_request",
    807 	.tp_setattro = PyObject_GenericSetAttr,
    808 	.tp_getattro = PyObject_GenericGetAttr,
    809 	.tp_getset = pyhttp_request_getset,
    810 	.tp_methods = pyhttp_request_methods,
    811 	.tp_dealloc = (destructor)pyhttp_dealloc,
    812 	.tp_basicsize = sizeof(struct pyhttp_request),
    813 	.tp_dictoffset = offsetof(struct pyhttp_request, dict),
    814 	.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
    815 };
    816 
    817 static PyObject	*pyhttp_file_read(struct pyhttp_file *, PyObject *);
    818 
    819 static PyMethodDef pyhttp_file_methods[] = {
    820 	METHOD("read", pyhttp_file_read, METH_VARARGS),
    821 	METHOD(NULL, NULL, -1)
    822 };
    823 
    824 static PyObject	*pyhttp_file_get_name(struct pyhttp_file *, void *);
    825 static PyObject	*pyhttp_file_get_filename(struct pyhttp_file *, void *);
    826 
    827 static PyGetSetDef pyhttp_file_getset[] = {
    828 	GETTER("name", pyhttp_file_get_name),
    829 	GETTER("filename", pyhttp_file_get_filename),
    830 	GETTER(NULL, NULL)
    831 };
    832 
    833 static PyTypeObject pyhttp_file_type = {
    834 	PyVarObject_HEAD_INIT(NULL, 0)
    835 	.tp_name = "kore.http_file",
    836 	.tp_doc = "struct http_file",
    837 	.tp_getset = pyhttp_file_getset,
    838 	.tp_methods = pyhttp_file_methods,
    839 	.tp_dealloc = (destructor)pyhttp_file_dealloc,
    840 	.tp_basicsize = sizeof(struct pyhttp_file),
    841 	.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
    842 };
    843 
    844 #if defined(KORE_USE_CURL)
    845 
    846 #define CURL_CLIENT_OP_RUN	1
    847 #define CURL_CLIENT_OP_RESULT	2
    848 
    849 struct pycurl_slist {
    850 	struct curl_slist		*slist;
    851 	LIST_ENTRY(pycurl_slist)	list;
    852 };
    853 
    854 struct pycurl_data {
    855 	struct kore_curl		curl;
    856 	LIST_HEAD(, pycurl_slist)	slists;
    857 };
    858 
    859 struct pycurl_handle {
    860 	PyObject_HEAD
    861 	char			*url;
    862 	struct kore_buf		*body;
    863 	struct pycurl_data	data;
    864 };
    865 
    866 struct pycurl_handle_op {
    867 	PyObject_HEAD
    868 	int			state;
    869 	struct python_coro	*coro;
    870 	struct pycurl_handle	*handle;
    871 };
    872 
    873 static PyObject	*pycurl_handle_op_await(PyObject *);
    874 static PyObject	*pycurl_handle_op_iternext(struct pycurl_handle_op *);
    875 
    876 static void	pycurl_handle_dealloc(struct pycurl_handle *);
    877 static void	pycurl_handle_op_dealloc(struct pycurl_handle_op *);
    878 
    879 static PyObject *pycurl_handle_run(struct pycurl_handle *, PyObject *);
    880 static PyObject *pycurl_handle_setopt(struct pycurl_handle *, PyObject *);
    881 static PyObject *pycurl_handle_setbody(struct pycurl_handle *, PyObject *);
    882 
    883 static PyObject *pycurl_handle_setopt_string(struct pycurl_data *,
    884 		    int, PyObject *);
    885 static PyObject *pycurl_handle_setopt_long(struct pycurl_data *,
    886 		    int, PyObject *);
    887 static PyObject *pycurl_handle_setopt_slist(struct pycurl_data *,
    888 		    int, PyObject *);
    889 
    890 static PyMethodDef pycurl_handle_methods[] = {
    891 	METHOD("run", pycurl_handle_run, METH_VARARGS),
    892 	METHOD("setopt", pycurl_handle_setopt, METH_VARARGS),
    893 	METHOD("setbody", pycurl_handle_setbody, METH_VARARGS),
    894 	METHOD(NULL, NULL, -1)
    895 };
    896 
    897 static PyTypeObject pycurl_handle_type = {
    898 	PyVarObject_HEAD_INIT(NULL, 0)
    899 	.tp_name = "kore.curl",
    900 	.tp_doc = "An asynchronous CURL handle",
    901 	.tp_methods = pycurl_handle_methods,
    902 	.tp_basicsize = sizeof(struct pycurl_handle),
    903 	.tp_dealloc = (destructor)pycurl_handle_dealloc,
    904 	.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
    905 };
    906 
    907 static PyAsyncMethods pycurl_handle_op_async = {
    908 	(unaryfunc)pycurl_handle_op_await,
    909 	NULL,
    910 	NULL
    911 };
    912 
    913 static PyTypeObject pycurl_handle_op_type = {
    914 	PyVarObject_HEAD_INIT(NULL, 0)
    915 	.tp_name = "kore.curlop",
    916 	.tp_doc = "Asynchronous CURL operation",
    917 	.tp_as_async = &pycurl_handle_op_async,
    918 	.tp_iternext = (iternextfunc)pycurl_handle_op_iternext,
    919 	.tp_basicsize = sizeof(struct pycurl_handle_op),
    920 	.tp_dealloc = (destructor)pycurl_handle_op_dealloc,
    921 	.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
    922 };
    923 
    924 struct pyhttp_client {
    925 	PyObject_HEAD
    926 	char			*url;
    927 	char			*unix;
    928 	char			*tlskey;
    929 	char			*tlscert;
    930 	char			*cabundle;
    931 	PyObject		*curlopt;
    932 	int			tlsverify;
    933 };
    934 
    935 struct pyhttp_client_op {
    936 	PyObject_HEAD
    937 	int			state;
    938 	int			headers;
    939 	struct python_coro	*coro;
    940 	struct pyhttp_client	*client;
    941 	struct pycurl_data	data;
    942 };
    943 
    944 
    945 static PyObject	*pyhttp_client_op_await(PyObject *);
    946 static PyObject	*pyhttp_client_op_iternext(struct pyhttp_client_op *);
    947 
    948 static void	pyhttp_client_dealloc(struct pyhttp_client *);
    949 static void	pyhttp_client_op_dealloc(struct pyhttp_client_op *);
    950 
    951 static PyObject *pyhttp_client_get(struct pyhttp_client *,
    952 		    PyObject *, PyObject *);
    953 static PyObject *pyhttp_client_put(struct pyhttp_client *,
    954 		    PyObject *, PyObject *);
    955 static PyObject *pyhttp_client_post(struct pyhttp_client *,
    956 		    PyObject *, PyObject *);
    957 static PyObject *pyhttp_client_head(struct pyhttp_client *,
    958 		    PyObject *, PyObject *);
    959 static PyObject *pyhttp_client_patch(struct pyhttp_client *,
    960 		    PyObject *, PyObject *);
    961 static PyObject *pyhttp_client_delete(struct pyhttp_client *,
    962 		    PyObject *, PyObject *);
    963 static PyObject *pyhttp_client_options(struct pyhttp_client *,
    964 		    PyObject *, PyObject *);
    965 
    966 static PyMethodDef pyhttp_client_methods[] = {
    967 	METHOD("get", pyhttp_client_get, METH_VARARGS | METH_KEYWORDS),
    968 	METHOD("put", pyhttp_client_put, METH_VARARGS | METH_KEYWORDS),
    969 	METHOD("post", pyhttp_client_post, METH_VARARGS | METH_KEYWORDS),
    970 	METHOD("head", pyhttp_client_head, METH_VARARGS | METH_KEYWORDS),
    971 	METHOD("patch", pyhttp_client_patch, METH_VARARGS | METH_KEYWORDS),
    972 	METHOD("delete", pyhttp_client_delete, METH_VARARGS | METH_KEYWORDS),
    973 	METHOD("options", pyhttp_client_options, METH_VARARGS | METH_KEYWORDS),
    974 	METHOD(NULL, NULL, -1)
    975 };
    976 
    977 static PyTypeObject pyhttp_client_type = {
    978 	PyVarObject_HEAD_INIT(NULL, 0)
    979 	.tp_name = "kore.httpclient",
    980 	.tp_doc = "An asynchronous HTTP client",
    981 	.tp_methods = pyhttp_client_methods,
    982 	.tp_basicsize = sizeof(struct pyhttp_client),
    983 	.tp_dealloc = (destructor)pyhttp_client_dealloc,
    984 	.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
    985 };
    986 
    987 static PyAsyncMethods pyhttp_client_op_async = {
    988 	(unaryfunc)pyhttp_client_op_await,
    989 	NULL,
    990 	NULL
    991 };
    992 
    993 static PyTypeObject pyhttp_client_op_type = {
    994 	PyVarObject_HEAD_INIT(NULL, 0)
    995 	.tp_name = "kore.httpclientop",
    996 	.tp_doc = "Asynchronous HTTP client operation",
    997 	.tp_as_async = &pyhttp_client_op_async,
    998 	.tp_iternext = (iternextfunc)pyhttp_client_op_iternext,
    999 	.tp_basicsize = sizeof(struct pyhttp_client_op),
   1000 	.tp_dealloc = (destructor)pyhttp_client_op_dealloc,
   1001 	.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
   1002 };
   1003 #endif
   1004 
   1005 #if defined(KORE_USE_PGSQL)
   1006 
   1007 #define PYKORE_PGSQL_PREINIT		1
   1008 #define PYKORE_PGSQL_INITIALIZE		2
   1009 #define PYKORE_PGSQL_QUERY		3
   1010 #define PYKORE_PGSQL_WAIT		4
   1011 
   1012 struct pykore_pgsql {
   1013 	PyObject_HEAD
   1014 	struct kore_pgsql	sql;
   1015 	int			state;
   1016 	int			binary;
   1017 
   1018 	char			*db;
   1019 	struct python_coro	*coro;
   1020 	char			*query;
   1021 	PyObject		*result;
   1022 
   1023 	struct {
   1024 		int		count;
   1025 		const char	**values;
   1026 		int		*lengths;
   1027 		int		*formats;
   1028 		PyObject	**objs;
   1029 	} param;
   1030 };
   1031 
   1032 static void	pykore_pgsql_dealloc(struct pykore_pgsql *);
   1033 
   1034 static PyObject	*pykore_pgsql_await(PyObject *);
   1035 static PyObject	*pykore_pgsql_iternext(struct pykore_pgsql *);
   1036 
   1037 static PyAsyncMethods pykore_pgsql_async = {
   1038 	(unaryfunc)pykore_pgsql_await,
   1039 	NULL,
   1040 	NULL
   1041 };
   1042 
   1043 static PyTypeObject pykore_pgsql_type = {
   1044 	PyVarObject_HEAD_INIT(NULL, 0)
   1045 	.tp_name = "kore.pgsql",
   1046 	.tp_doc = "struct kore_pgsql",
   1047 	.tp_as_async = &pykore_pgsql_async,
   1048 	.tp_iternext = (iternextfunc)pykore_pgsql_iternext,
   1049 	.tp_basicsize = sizeof(struct pykore_pgsql),
   1050 	.tp_dealloc = (destructor)pykore_pgsql_dealloc,
   1051 	.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
   1052 };
   1053 #endif