mirror of
https://github.com/samba-team/samba.git
synced 2025-01-12 09:18:10 +03:00
Implement IRPC calls over the internal messaging bus.
(This used to be commit 777dc3a2c7
)
This commit is contained in:
parent
fd712bb878
commit
d60d8e57d8
@ -22,11 +22,13 @@
|
||||
#include "includes.h"
|
||||
#include <Python.h>
|
||||
#include "libcli/util/pyerrors.h"
|
||||
#include "librpc/rpc/pyrpc.h"
|
||||
#include "lib/messaging/irpc.h"
|
||||
#include "lib/messaging/messaging.h"
|
||||
#include "lib/events/events.h"
|
||||
#include "cluster/cluster.h"
|
||||
#include "param/param.h"
|
||||
#include "librpc/gen_ndr/py_irpc.h"
|
||||
|
||||
PyAPI_DATA(PyTypeObject) messaging_Type;
|
||||
PyAPI_DATA(PyTypeObject) irpc_InterfaceType;
|
||||
@ -360,6 +362,126 @@ PyObject *py_irpc_connect(PyTypeObject *self, PyObject *args, PyObject *kwargs)
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
struct irpc_request **reqs;
|
||||
int count;
|
||||
int current;
|
||||
TALLOC_CTX *mem_ctx;
|
||||
py_data_unpack_fn unpack_fn;
|
||||
} irpc_ResultObject;
|
||||
|
||||
|
||||
static PyObject *irpc_result_next(irpc_ResultObject *iterator)
|
||||
{
|
||||
NTSTATUS status;
|
||||
|
||||
if (iterator->current >= iterator->count) {
|
||||
PyErr_SetString(PyExc_StopIteration, "No more results");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
status = irpc_call_recv(iterator->reqs[iterator->current]);
|
||||
iterator->current++;
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
PyErr_SetNTSTATUS(status);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return iterator->unpack_fn(iterator->reqs[iterator->current-1]->r);
|
||||
}
|
||||
|
||||
static PyObject *irpc_result_len(irpc_ResultObject *self)
|
||||
{
|
||||
return PyLong_FromLong(self->count);
|
||||
}
|
||||
|
||||
static PyMethodDef irpc_result_methods[] = {
|
||||
{ "__len__", (PyCFunction)irpc_result_len, METH_NOARGS,
|
||||
"Number of elements returned"},
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static void irpc_result_dealloc(PyObject *self)
|
||||
{
|
||||
talloc_free(((irpc_ResultObject *)self)->mem_ctx);
|
||||
PyObject_Del(self);
|
||||
}
|
||||
|
||||
PyTypeObject irpc_ResultIteratorType = {
|
||||
PyObject_HEAD_INIT(NULL) 0,
|
||||
.tp_name = "irpc.ResultIterator",
|
||||
.tp_basicsize = sizeof(irpc_ResultObject),
|
||||
.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
|
||||
.tp_iter = (iternextfunc)irpc_result_next,
|
||||
.tp_methods = irpc_result_methods,
|
||||
.tp_dealloc = irpc_result_dealloc,
|
||||
};
|
||||
|
||||
static PyObject *py_irpc_call(irpc_InterfaceObject *p, struct PyNdrRpcMethodDef *method_def, PyObject *args, PyObject *kwargs)
|
||||
{
|
||||
void *ptr;
|
||||
struct irpc_request **reqs;
|
||||
int i, count;
|
||||
NTSTATUS status;
|
||||
TALLOC_CTX *mem_ctx = talloc_new(NULL);
|
||||
irpc_ResultObject *ret;
|
||||
|
||||
/* allocate the C structure */
|
||||
ptr = talloc_zero_size(mem_ctx, method_def->table->calls[method_def->opnum].struct_size);
|
||||
if (ptr == NULL) {
|
||||
status = NT_STATUS_NO_MEMORY;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* convert the mpr object into a C structure */
|
||||
if (!method_def->pack_in_data(args, kwargs, ptr)) {
|
||||
talloc_free(mem_ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (count=0;p->dest_ids[count].id;count++) /* noop */ ;
|
||||
|
||||
/* we need to make a call per server */
|
||||
reqs = talloc_array(mem_ctx, struct irpc_request *, count);
|
||||
if (reqs == NULL) {
|
||||
status = NT_STATUS_NO_MEMORY;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* make the actual calls */
|
||||
for (i=0;i<count;i++) {
|
||||
reqs[i] = irpc_call_send(p->msg_ctx, p->dest_ids[i],
|
||||
method_def->table, method_def->opnum, ptr, ptr);
|
||||
if (reqs[i] == NULL) {
|
||||
status = NT_STATUS_NO_MEMORY;
|
||||
goto done;
|
||||
}
|
||||
talloc_steal(reqs, reqs[i]);
|
||||
}
|
||||
|
||||
ret = PyObject_New(irpc_ResultObject, &irpc_ResultIteratorType);
|
||||
ret->mem_ctx = mem_ctx;
|
||||
ret->reqs = reqs;
|
||||
ret->count = count;
|
||||
ret->current = 0;
|
||||
ret->unpack_fn = method_def->unpack_out_data;
|
||||
|
||||
return (PyObject *)ret;
|
||||
done:
|
||||
talloc_free(mem_ctx);
|
||||
PyErr_SetNTSTATUS(status);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static PyObject *py_irpc_call_wrapper(PyObject *self, PyObject *args, void *wrapped, PyObject *kwargs)
|
||||
{
|
||||
irpc_InterfaceObject *iface = (irpc_InterfaceObject *)self;
|
||||
struct PyNdrRpcMethodDef *md = wrapped;
|
||||
|
||||
return py_irpc_call(iface, md, args, kwargs);
|
||||
}
|
||||
|
||||
static void py_irpc_dealloc(PyObject *self)
|
||||
{
|
||||
irpc_InterfaceObject *iface = (irpc_InterfaceObject *)self;
|
||||
@ -376,105 +498,26 @@ PyTypeObject irpc_InterfaceType = {
|
||||
.tp_dealloc = py_irpc_dealloc,
|
||||
};
|
||||
|
||||
#if 0
|
||||
/*
|
||||
make an irpc call - called via the same interface as rpc
|
||||
*/
|
||||
static int ejs_irpc_call(int eid, struct MprVar *io,
|
||||
const struct ndr_interface_table *iface, int callnum,
|
||||
ejs_pull_function_t ejs_pull, ejs_push_function_t ejs_push)
|
||||
static bool irpc_AddNdrRpcMethods(PyTypeObject *ifacetype, struct PyNdrRpcMethodDef *mds)
|
||||
{
|
||||
NTSTATUS status;
|
||||
void *ptr;
|
||||
struct ejs_rpc *ejs;
|
||||
const struct ndr_interface_call *call;
|
||||
struct ejs_irpc_connection *p;
|
||||
struct irpc_request **reqs;
|
||||
int i, count;
|
||||
struct MprVar *results;
|
||||
int i;
|
||||
for (i = 0; mds[i].name; i++) {
|
||||
PyObject *ret;
|
||||
struct wrapperbase *wb = calloc(sizeof(struct wrapperbase), 1);
|
||||
|
||||
p = (struct ejs_irpc_connection *)mprGetThisPtr(eid, "irpc");
|
||||
wb->name = discard_const_p(char, mds[i].name);
|
||||
wb->flags = PyWrapperFlag_KEYWORDS;
|
||||
wb->wrapper = (wrapperfunc)py_irpc_call_wrapper;
|
||||
wb->doc = discard_const_p(char, mds[i].doc);
|
||||
|
||||
ret = PyDescr_NewWrapper(ifacetype, wb, &mds[i]);
|
||||
|
||||
ejs = talloc(mprMemCtx(), struct ejs_rpc);
|
||||
if (ejs == NULL) {
|
||||
status = NT_STATUS_NO_MEMORY;
|
||||
goto done;
|
||||
PyDict_SetItemString(ifacetype->tp_dict, mds[i].name,
|
||||
(PyObject *)ret);
|
||||
}
|
||||
|
||||
call = &iface->calls[callnum];
|
||||
|
||||
ejs->eid = eid;
|
||||
ejs->callname = call->name;
|
||||
|
||||
/* allocate the C structure */
|
||||
ptr = talloc_zero_size(ejs, call->struct_size);
|
||||
if (ptr == NULL) {
|
||||
status = NT_STATUS_NO_MEMORY;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* convert the mpr object into a C structure */
|
||||
status = ejs_pull(ejs, io, ptr);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
for (count=0;p->dest_ids[count].id;count++) /* noop */ ;
|
||||
|
||||
/* we need to make a call per server */
|
||||
reqs = talloc_array(ejs, struct irpc_request *, count);
|
||||
if (reqs == NULL) {
|
||||
status = NT_STATUS_NO_MEMORY;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* make the actual calls */
|
||||
for (i=0;i<count;i++) {
|
||||
reqs[i] = irpc_call_send(p->msg_ctx, p->dest_ids[i],
|
||||
iface, callnum, ptr, ptr);
|
||||
if (reqs[i] == NULL) {
|
||||
status = NT_STATUS_NO_MEMORY;
|
||||
goto done;
|
||||
}
|
||||
talloc_steal(reqs, reqs[i]);
|
||||
}
|
||||
|
||||
mprSetVar(io, "results", mprObject("results"));
|
||||
results = mprGetProperty(io, "results", NULL);
|
||||
|
||||
/* and receive the results, placing them in io.results[i] */
|
||||
for (i=0;i<count;i++) {
|
||||
struct MprVar *output;
|
||||
|
||||
status = irpc_call_recv(reqs[i]);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
goto done;
|
||||
}
|
||||
status = ejs_push(ejs, io, ptr);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* add to the results array */
|
||||
output = mprGetProperty(io, "output", NULL);
|
||||
if (output) {
|
||||
char idx[16];
|
||||
mprItoa(i, idx, sizeof(idx));
|
||||
mprSetProperty(results, idx, output);
|
||||
mprDeleteProperty(io, "output");
|
||||
}
|
||||
}
|
||||
mprSetVar(results, "length", mprCreateIntegerVar(i));
|
||||
|
||||
done:
|
||||
talloc_free(ejs);
|
||||
mpr_Return(eid, mprNTSTATUS(status));
|
||||
if (NT_STATUS_EQUAL(status, NT_STATUS_INTERNAL_ERROR)) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
void initirpc(void)
|
||||
{
|
||||
@ -486,6 +529,12 @@ void initirpc(void)
|
||||
if (PyType_Ready(&messaging_Type) < 0)
|
||||
return;
|
||||
|
||||
if (PyType_Ready(&irpc_ResultIteratorType) < 0)
|
||||
return;
|
||||
|
||||
if (!irpc_AddNdrRpcMethods(&irpc_InterfaceType, py_ndr_irpc_methods))
|
||||
return;
|
||||
|
||||
mod = Py_InitModule3("irpc", NULL, "Internal RPC");
|
||||
if (mod == NULL)
|
||||
return;
|
||||
|
@ -71,7 +71,7 @@ static PyObject *py_dcerpc_call_wrapper(PyObject *self, PyObject *args, void *wr
|
||||
}
|
||||
|
||||
|
||||
bool PyInterface_AddNdrRpcMethods(PyTypeObject *ifacetype, struct PyNdrRpcMethodDef *mds)
|
||||
bool PyInterface_AddNdrRpcMethods(PyTypeObject *ifacetype, const struct PyNdrRpcMethodDef *mds)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; mds[i].name; i++) {
|
||||
@ -83,7 +83,7 @@ bool PyInterface_AddNdrRpcMethods(PyTypeObject *ifacetype, struct PyNdrRpcMethod
|
||||
wb->wrapper = (wrapperfunc)py_dcerpc_call_wrapper;
|
||||
wb->doc = discard_const_p(char, mds[i].doc);
|
||||
|
||||
ret = PyDescr_NewWrapper(ifacetype, wb, &mds[i]);
|
||||
ret = PyDescr_NewWrapper(ifacetype, wb, discard_const_p(void, &mds[i]));
|
||||
|
||||
PyDict_SetItemString(ifacetype->tp_dict, mds[i].name,
|
||||
(PyObject *)ret);
|
||||
|
@ -66,6 +66,6 @@ struct PyNdrRpcMethodDef {
|
||||
const struct ndr_interface_table *table;
|
||||
};
|
||||
|
||||
bool PyInterface_AddNdrRpcMethods(PyTypeObject *object, struct PyNdrRpcMethodDef *mds);
|
||||
bool PyInterface_AddNdrRpcMethods(PyTypeObject *object, const struct PyNdrRpcMethodDef *mds);
|
||||
|
||||
#endif /* _PYRPC_H_ */
|
||||
|
@ -650,7 +650,8 @@ sub Interface($$$)
|
||||
push (@fns, [$infn, $outfn, "dcerpc_$d->{NAME}", $prettyname, $fndocstring, $d->{OPNUM}]);
|
||||
}
|
||||
|
||||
$self->pidl("static struct PyNdrRpcMethodDef interface_$interface->{NAME}\_methods[] = {");
|
||||
$self->pidl("const struct PyNdrRpcMethodDef py_ndr_$interface->{NAME}\_methods[] = {");
|
||||
$self->pidl_hdr("const struct PyNdrRpcMethodDef py_ndr_$interface->{NAME}\_methods[];");
|
||||
$self->indent;
|
||||
foreach my $d (@fns) {
|
||||
my ($infn, $outfn, $callfn, $prettyname, $docstring, $opnum) = @$d;
|
||||
@ -771,7 +772,7 @@ sub Interface($$$)
|
||||
$self->pidl("");
|
||||
|
||||
$self->register_module_typeobject($interface->{NAME}, "&$interface->{NAME}_InterfaceType");
|
||||
$self->register_module_readycode(["if (!PyInterface_AddNdrRpcMethods(&$interface->{NAME}_InterfaceType, interface_$interface->{NAME}_methods))", "\treturn;", ""]);
|
||||
$self->register_module_readycode(["if (!PyInterface_AddNdrRpcMethods(&$interface->{NAME}_InterfaceType, py_ndr_$interface->{NAME}\_methods))", "\treturn;", ""]);
|
||||
}
|
||||
|
||||
$self->pidl_hdr("\n");
|
||||
|
Loading…
Reference in New Issue
Block a user