Changeset 745 for trunk/server/source4/lib/messaging/pymessaging.c
- Timestamp:
- Nov 27, 2012, 4:43:17 PM (13 years ago)
- Location:
- trunk/server
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/server
- Property svn:mergeinfo changed
/vendor/current merged: 581,587,591,594,597,600,615,618,740
- Property svn:mergeinfo changed
-
trunk/server/source4/lib/messaging/pymessaging.c
r414 r745 20 20 */ 21 21 22 #include <Python.h> 22 23 #include "includes.h" 23 #include <Python.h>24 24 #include "scripting/python/modules.h" 25 25 #include "libcli/util/pyerrors.h" 26 #include "librpc/rpc/pyrpc .h"27 #include "lib /messaging/irpc.h"26 #include "librpc/rpc/pyrpc_util.h" 27 #include "librpc/ndr/libndr.h" 28 28 #include "lib/messaging/messaging.h" 29 29 #include "lib/events/events.h" … … 31 31 #include "param/param.h" 32 32 #include "param/pyparam.h" 33 34 #ifndef Py_RETURN_NONE 35 #define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None 36 #endif 37 38 PyAPI_DATA(PyTypeObject) messaging_Type; 39 PyAPI_DATA(PyTypeObject) irpc_ClientConnectionType; 40 41 /* FIXME: This prototype should be in py_irpc.h, or shared otherwise */ 42 extern const struct PyNdrRpcMethodDef py_ndr_irpc_methods[]; 33 #include "librpc/rpc/dcerpc.h" 34 #include "librpc/gen_ndr/server_id4.h" 35 36 void initmessaging(void); 37 38 extern PyTypeObject messaging_Type; 43 39 44 40 static bool server_id_from_py(PyObject *object, struct server_id *server_id) … … 66 62 } messaging_Object; 67 63 68 PyObject *py_messaging_connect(PyTypeObject *self, PyObject *args, PyObject *kwargs)64 static PyObject *py_messaging_connect(PyTypeObject *self, PyObject *args, PyObject *kwargs) 69 65 { 70 66 struct tevent_context *ev; … … 88 84 89 85 if (messaging_path == NULL) { 90 messaging_path = lp _messaging_path(ret->mem_ctx,86 messaging_path = lpcfg_messaging_path(ret->mem_ctx, 91 87 py_default_loadparm_context(ret->mem_ctx)); 92 88 } else { … … 103 99 messaging_path, 104 100 server_id, 105 py_iconv_convenience(ret->mem_ctx),106 101 ev); 107 102 } else { 108 103 ret->msg_ctx = messaging_client_init(ret->mem_ctx, 109 104 messaging_path, 110 py_iconv_convenience(ret->mem_ctx),111 105 ev); 112 106 } … … 125 119 messaging_Object *iface = (messaging_Object *)self; 126 120 talloc_free(iface->msg_ctx); 127 PyObject_Del(self);121 self->ob_type->tp_free(self); 128 122 } 129 123 … … 139 133 int length; 140 134 141 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Ois# |:send",135 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Ois#:send", 142 136 discard_const_p(char *, kwnames), &target, &msg_type, &data.data, &length)) { 137 143 138 return NULL; 144 139 } … … 146 141 data.length = length; 147 142 148 if (!server_id_from_py(target, &server)) 143 if (!server_id_from_py(target, &server)) 149 144 return NULL; 150 145 … … 177 172 const char *kwnames[] = { "callback", "msg_type", NULL }; 178 173 179 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i: send",174 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:register", 180 175 discard_const_p(char *, kwnames), &callback, &msg_type)) { 181 176 return NULL; … … 208 203 const char *kwnames[] = { "callback", "msg_type", NULL }; 209 204 210 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i: send",205 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|i:deregister", 211 206 discard_const_p(char *, kwnames), &callback, &msg_type)) { 212 207 return NULL; … … 216 211 217 212 Py_DECREF(callback); 218 219 Py_RETURN_NONE;220 }221 222 static PyObject *py_messaging_add_name(PyObject *self, PyObject *args, PyObject *kwargs)223 {224 messaging_Object *iface = (messaging_Object *)self;225 NTSTATUS status;226 char *name;227 const char *kwnames[] = { "name", NULL };228 229 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|:send",230 discard_const_p(char *, kwnames), &name)) {231 return NULL;232 }233 234 status = irpc_add_name(iface->msg_ctx, name);235 if (NT_STATUS_IS_ERR(status)) {236 PyErr_SetNTSTATUS(status);237 return NULL;238 }239 240 Py_RETURN_NONE;241 }242 243 244 static PyObject *py_messaging_remove_name(PyObject *self, PyObject *args, PyObject *kwargs)245 {246 messaging_Object *iface = (messaging_Object *)self;247 char *name;248 const char *kwnames[] = { "name", NULL };249 250 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|:send",251 discard_const_p(char *, kwnames), &name)) {252 return NULL;253 }254 255 irpc_remove_name(iface->msg_ctx, name);256 213 257 214 Py_RETURN_NONE; … … 265 222 { "deregister", (PyCFunction)py_messaging_deregister, METH_VARARGS|METH_KEYWORDS, 266 223 "S.deregister(callback, msg_type) -> None\nDeregister a message handler" }, 267 { "add_name", (PyCFunction)py_messaging_add_name, METH_VARARGS|METH_KEYWORDS, "S.add_name(name) -> None\nListen on another name" },268 { "remove_name", (PyCFunction)py_messaging_remove_name, METH_VARARGS|METH_KEYWORDS, "S.remove_name(name) -> None\nStop listening on a name" },269 224 { NULL, NULL, 0, NULL } 270 225 }; … … 288 243 PyTypeObject messaging_Type = { 289 244 PyObject_HEAD_INIT(NULL) 0, 290 .tp_name = " irpc.Messaging",245 .tp_name = "messaging.Messaging", 291 246 .tp_basicsize = sizeof(messaging_Object), 292 247 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, … … 300 255 }; 301 256 302 303 /*304 state of a irpc 'connection'305 */306 typedef struct {307 PyObject_HEAD308 const char *server_name;309 struct server_id *dest_ids;310 struct messaging_context *msg_ctx;311 TALLOC_CTX *mem_ctx;312 } irpc_ClientConnectionObject;313 314 /*315 setup a context for talking to a irpc server316 example:317 status = irpc.connect("smb_server");318 */319 320 PyObject *py_irpc_connect(PyTypeObject *self, PyObject *args, PyObject *kwargs)321 {322 struct tevent_context *ev;323 const char *kwnames[] = { "server", "own_id", "messaging_path", NULL };324 char *server;325 const char *messaging_path = NULL;326 PyObject *own_id = Py_None;327 irpc_ClientConnectionObject *ret;328 329 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|Oz:connect",330 discard_const_p(char *, kwnames), &server, &own_id, &messaging_path)) {331 return NULL;332 }333 334 ret = PyObject_New(irpc_ClientConnectionObject, &irpc_ClientConnectionType);335 if (ret == NULL)336 return NULL;337 338 ret->mem_ctx = talloc_new(NULL);339 340 ret->server_name = server;341 342 ev = s4_event_context_init(ret->mem_ctx);343 344 if (messaging_path == NULL) {345 messaging_path = lp_messaging_path(ret->mem_ctx,346 py_default_loadparm_context(ret->mem_ctx));347 } else {348 messaging_path = talloc_strdup(ret->mem_ctx, messaging_path);349 }350 351 if (own_id != Py_None) {352 struct server_id server_id;353 354 if (!server_id_from_py(own_id, &server_id))355 return NULL;356 357 ret->msg_ctx = messaging_init(ret->mem_ctx,358 messaging_path,359 server_id,360 py_iconv_convenience(ret->mem_ctx),361 ev);362 } else {363 ret->msg_ctx = messaging_client_init(ret->mem_ctx,364 messaging_path,365 py_iconv_convenience(ret->mem_ctx),366 ev);367 }368 369 if (ret->msg_ctx == NULL) {370 PyErr_SetString(PyExc_RuntimeError, "irpc_connect unable to create a messaging context");371 talloc_free(ret->mem_ctx);372 return NULL;373 }374 375 ret->dest_ids = irpc_servers_byname(ret->msg_ctx, ret->mem_ctx, ret->server_name);376 if (ret->dest_ids == NULL || ret->dest_ids[0].id == 0) {377 talloc_free(ret->mem_ctx);378 PyErr_SetNTSTATUS(NT_STATUS_OBJECT_NAME_NOT_FOUND);379 return NULL;380 } else {381 return (PyObject *)ret;382 }383 }384 385 typedef struct {386 PyObject_HEAD387 struct irpc_request **reqs;388 int count;389 int current;390 TALLOC_CTX *mem_ctx;391 py_data_unpack_fn unpack_fn;392 } irpc_ResultObject;393 394 395 static PyObject *irpc_result_next(irpc_ResultObject *iterator)396 {397 NTSTATUS status;398 399 if (iterator->current >= iterator->count) {400 PyErr_SetString(PyExc_StopIteration, "No more results");401 return NULL;402 }403 404 status = irpc_call_recv(iterator->reqs[iterator->current]);405 iterator->current++;406 if (!NT_STATUS_IS_OK(status)) {407 PyErr_SetNTSTATUS(status);408 return NULL;409 }410 411 return iterator->unpack_fn(iterator->reqs[iterator->current-1]->r);412 }413 414 static PyObject *irpc_result_len(irpc_ResultObject *self)415 {416 return PyLong_FromLong(self->count);417 }418 419 static PyMethodDef irpc_result_methods[] = {420 { "__len__", (PyCFunction)irpc_result_len, METH_NOARGS,421 "Number of elements returned"},422 { NULL }423 };424 425 static void irpc_result_dealloc(PyObject *self)426 {427 talloc_free(((irpc_ResultObject *)self)->mem_ctx);428 PyObject_Del(self);429 }430 431 PyTypeObject irpc_ResultIteratorType = {432 PyObject_HEAD_INIT(NULL) 0,433 .tp_name = "irpc.ResultIterator",434 .tp_basicsize = sizeof(irpc_ResultObject),435 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,436 .tp_iternext = (iternextfunc)irpc_result_next,437 .tp_iter = PyObject_SelfIter,438 .tp_methods = irpc_result_methods,439 .tp_dealloc = irpc_result_dealloc,440 };441 442 static PyObject *py_irpc_call(irpc_ClientConnectionObject *p, struct PyNdrRpcMethodDef *method_def, PyObject *args, PyObject *kwargs)443 {444 void *ptr;445 struct irpc_request **reqs;446 int i, count;447 NTSTATUS status;448 TALLOC_CTX *mem_ctx = talloc_new(NULL);449 irpc_ResultObject *ret;450 451 /* allocate the C structure */452 ptr = talloc_zero_size(mem_ctx, method_def->table->calls[method_def->opnum].struct_size);453 if (ptr == NULL) {454 status = NT_STATUS_NO_MEMORY;455 goto done;456 }457 458 /* convert the mpr object into a C structure */459 if (!method_def->pack_in_data(args, kwargs, ptr)) {460 talloc_free(mem_ctx);461 return NULL;462 }463 464 for (count=0;p->dest_ids[count].id;count++) /* noop */ ;465 466 /* we need to make a call per server */467 reqs = talloc_array(mem_ctx, struct irpc_request *, count);468 if (reqs == NULL) {469 status = NT_STATUS_NO_MEMORY;470 goto done;471 }472 473 /* make the actual calls */474 for (i=0;i<count;i++) {475 reqs[i] = irpc_call_send(p->msg_ctx, p->dest_ids[i],476 method_def->table, method_def->opnum, ptr, ptr);477 if (reqs[i] == NULL) {478 status = NT_STATUS_NO_MEMORY;479 goto done;480 }481 talloc_steal(reqs, reqs[i]);482 }483 484 ret = PyObject_New(irpc_ResultObject, &irpc_ResultIteratorType);485 ret->mem_ctx = mem_ctx;486 ret->reqs = reqs;487 ret->count = count;488 ret->current = 0;489 ret->unpack_fn = method_def->unpack_out_data;490 491 return (PyObject *)ret;492 done:493 talloc_free(mem_ctx);494 PyErr_SetNTSTATUS(status);495 return NULL;496 }497 498 static PyObject *py_irpc_call_wrapper(PyObject *self, PyObject *args, void *wrapped, PyObject *kwargs)499 {500 irpc_ClientConnectionObject *iface = (irpc_ClientConnectionObject *)self;501 struct PyNdrRpcMethodDef *md = wrapped;502 503 return py_irpc_call(iface, md, args, kwargs);504 }505 506 static void py_irpc_dealloc(PyObject *self)507 {508 irpc_ClientConnectionObject *iface = (irpc_ClientConnectionObject *)self;509 talloc_free(iface->mem_ctx);510 PyObject_Del(self);511 }512 513 PyTypeObject irpc_ClientConnectionType = {514 PyObject_HEAD_INIT(NULL) 0,515 .tp_name = "irpc.ClientConnection",516 .tp_basicsize = sizeof(irpc_ClientConnectionObject),517 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,518 .tp_new = py_irpc_connect,519 .tp_dealloc = py_irpc_dealloc,520 .tp_doc = "ClientConnection(server, own_id=None, messaging_path=None)\n" \521 "Create a new IRPC client connection to communicate with the servers in the specified path.\n" \522 "If no path is specified, the default path from smb.conf will be used."523 };524 525 static bool irpc_AddNdrRpcMethods(PyTypeObject *ifacetype, const struct PyNdrRpcMethodDef *mds)526 {527 int i;528 for (i = 0; mds[i].name; i++) {529 PyObject *ret;530 struct wrapperbase *wb = calloc(sizeof(struct wrapperbase), 1);531 532 wb->name = discard_const_p(char, mds[i].name);533 wb->flags = PyWrapperFlag_KEYWORDS;534 wb->wrapper = (wrapperfunc)py_irpc_call_wrapper;535 wb->doc = discard_const_p(char, mds[i].doc);536 537 ret = PyDescr_NewWrapper(ifacetype, wb, discard_const_p(void, &mds[i]));538 539 PyDict_SetItemString(ifacetype->tp_dict, mds[i].name,540 (PyObject *)ret);541 }542 543 return true;544 }545 546 257 void initmessaging(void) 547 258 { 548 259 PyObject *mod; 549 PyObject *dep_irpc;550 551 dep_irpc = PyImport_ImportModule("samba.dcerpc.irpc");552 if (dep_irpc == NULL)553 return;554 555 if (PyType_Ready(&irpc_ClientConnectionType) < 0)556 return;557 260 558 261 if (PyType_Ready(&messaging_Type) < 0) 559 return;560 561 if (PyType_Ready(&irpc_ResultIteratorType) < 0)562 return;563 564 if (!irpc_AddNdrRpcMethods(&irpc_ClientConnectionType, py_ndr_irpc_methods))565 262 return; 566 263 … … 569 266 return; 570 267 571 Py_INCREF((PyObject *)&irpc_ClientConnectionType);572 PyModule_AddObject(mod, "ClientConnection", (PyObject *)&irpc_ClientConnectionType);573 574 268 Py_INCREF((PyObject *)&messaging_Type); 575 269 PyModule_AddObject(mod, "Messaging", (PyObject *)&messaging_Type);
Note:
See TracChangeset
for help on using the changeset viewer.