2008-05-24 18:18:21 +02:00
/*
Unix SMB / CIFS implementation .
Copyright © Jelmer Vernooij < jelmer @ samba . org > 2008
Based on the equivalent for EJS :
Copyright © Andrew Tridgell < tridge @ samba . org > 2005
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 3 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
2009-01-08 12:20:20 +01:00
# include <Python.h>
2009-10-23 16:23:01 +11:00
# include "includes.h"
2012-12-28 15:37:14 +01:00
# include "python/modules.h"
2008-05-25 16:26:34 +02:00
# include "libcli/util/pyerrors.h"
2010-09-03 02:39:38 +02:00
# include "librpc/rpc/pyrpc_util.h"
2010-03-18 19:36:50 +01:00
# include "librpc/ndr/libndr.h"
2008-05-26 01:52:35 +02:00
# include "lib/messaging/messaging.h"
2012-10-29 15:33:59 +11:00
# include "lib/messaging/irpc.h"
2008-05-25 16:26:34 +02:00
# include "lib/events/events.h"
# include "cluster/cluster.h"
# include "param/param.h"
2009-06-02 15:00:41 +02:00
# include "param/pyparam.h"
2010-09-03 15:21:16 +02:00
# include "librpc/rpc/dcerpc.h"
2011-05-02 10:55:20 +10:00
# include "librpc/gen_ndr/server_id.h"
2012-10-29 15:33:59 +11:00
# include <pytalloc.h>
2008-05-24 18:18:21 +02:00
2010-12-29 18:09:09 +01:00
void initmessaging ( void ) ;
2011-05-03 10:40:33 +10:00
extern PyTypeObject imessaging_Type ;
2008-12-22 04:21:20 +01:00
2008-05-26 01:10:24 +02:00
static bool server_id_from_py ( PyObject * object , struct server_id * server_id )
{
if ( ! PyTuple_Check ( object ) ) {
2013-09-18 14:29:26 -07:00
if ( ! py_check_dcerpc_type ( object , " samba.dcerpc.server_id " , " server_id " ) ) {
2008-05-26 01:10:24 +02:00
2012-10-29 15:33:59 +11:00
PyErr_SetString ( PyExc_ValueError , " Expected tuple or server_id " ) ;
return false ;
}
* server_id = * pytalloc_get_type ( object , struct server_id ) ;
return true ;
}
2008-05-26 01:52:35 +02:00
if ( PyTuple_Size ( object ) = = 3 ) {
2014-11-27 12:28:40 +01:00
unsigned long long pid ;
int task_id , vnn ;
if ( ! PyArg_ParseTuple ( object , " KII " , & pid , & task_id , & vnn ) ) {
return false ;
}
server_id - > pid = pid ;
server_id - > task_id = task_id ;
server_id - > vnn = vnn ;
return true ;
2008-05-26 01:52:35 +02:00
} else {
2014-11-27 12:28:40 +01:00
unsigned long long pid ;
int task_id ;
2013-01-26 08:58:46 +11:00
if ( ! PyArg_ParseTuple ( object , " KI " , & pid , & task_id ) )
2008-05-26 01:52:35 +02:00
return false ;
2011-05-08 18:28:17 +02:00
* server_id = cluster_id ( pid , task_id ) ;
2008-05-26 01:52:35 +02:00
return true ;
}
2008-05-26 01:10:24 +02:00
}
2008-05-25 16:26:34 +02:00
typedef struct {
PyObject_HEAD
TALLOC_CTX * mem_ctx ;
2011-05-03 10:40:33 +10:00
struct imessaging_context * msg_ctx ;
} imessaging_Object ;
2008-05-25 16:26:34 +02:00
2011-05-03 10:40:33 +10:00
static PyObject * py_imessaging_connect ( PyTypeObject * self , PyObject * args , PyObject * kwargs )
2008-05-25 16:26:34 +02:00
{
2008-12-29 20:24:57 +01:00
struct tevent_context * ev ;
2011-10-13 20:01:56 +11:00
const char * kwnames [ ] = { " own_id " , " lp_ctx " , NULL } ;
2008-05-26 01:10:24 +02:00
PyObject * own_id = Py_None ;
2011-10-13 20:01:56 +11:00
PyObject * py_lp_ctx = Py_None ;
2011-05-03 10:40:33 +10:00
imessaging_Object * ret ;
2011-10-13 20:01:56 +11:00
struct loadparm_context * lp_ctx ;
2008-05-25 16:26:34 +02:00
2011-10-13 20:01:56 +11:00
if ( ! PyArg_ParseTupleAndKeywords ( args , kwargs , " |OO:connect " ,
discard_const_p ( char * , kwnames ) , & own_id , & py_lp_ctx ) ) {
2008-05-25 16:26:34 +02:00
return NULL ;
}
2011-05-03 10:40:33 +10:00
ret = PyObject_New ( imessaging_Object , & imessaging_Type ) ;
2008-05-25 16:26:34 +02:00
if ( ret = = NULL )
return NULL ;
ret - > mem_ctx = talloc_new ( NULL ) ;
2011-10-13 20:01:56 +11:00
lp_ctx = lpcfg_from_py_object ( ret - > mem_ctx , py_lp_ctx ) ;
if ( lp_ctx = = NULL ) {
PyErr_SetString ( PyExc_RuntimeError , " imessaging_connect unable to interpret loadparm_context " ) ;
talloc_free ( ret - > mem_ctx ) ;
return NULL ;
2008-05-25 16:26:34 +02:00
}
2011-10-13 20:01:56 +11:00
ev = s4_event_context_init ( ret - > mem_ctx ) ;
2008-05-26 01:10:24 +02:00
if ( own_id ! = Py_None ) {
struct server_id server_id ;
if ( ! server_id_from_py ( own_id , & server_id ) )
return NULL ;
2011-05-03 10:40:33 +10:00
ret - > msg_ctx = imessaging_init ( ret - > mem_ctx ,
2011-10-13 20:01:56 +11:00
lp_ctx ,
2011-07-22 14:55:32 +10:00
server_id ,
ev , true ) ;
2008-05-26 01:10:24 +02:00
} else {
2011-05-03 10:40:33 +10:00
ret - > msg_ctx = imessaging_client_init ( ret - > mem_ctx ,
2011-10-13 20:01:56 +11:00
lp_ctx ,
2011-07-22 14:55:32 +10:00
ev ) ;
2008-05-25 16:26:34 +02:00
}
if ( ret - > msg_ctx = = NULL ) {
2011-05-03 10:40:33 +10:00
PyErr_SetString ( PyExc_RuntimeError , " imessaging_connect unable to create a messaging context " ) ;
2008-05-25 16:26:34 +02:00
talloc_free ( ret - > mem_ctx ) ;
return NULL ;
}
return ( PyObject * ) ret ;
}
2011-05-03 10:40:33 +10:00
static void py_imessaging_dealloc ( PyObject * self )
2008-05-25 16:26:34 +02:00
{
2011-05-03 10:40:33 +10:00
imessaging_Object * iface = ( imessaging_Object * ) self ;
2008-05-25 16:26:34 +02:00
talloc_free ( iface - > msg_ctx ) ;
2010-12-29 18:56:13 +01:00
self - > ob_type - > tp_free ( self ) ;
2008-05-25 16:26:34 +02:00
}
2011-05-03 10:40:33 +10:00
static PyObject * py_imessaging_send ( PyObject * self , PyObject * args , PyObject * kwargs )
2008-05-25 16:26:34 +02:00
{
2011-05-03 10:40:33 +10:00
imessaging_Object * iface = ( imessaging_Object * ) self ;
2008-05-26 01:10:24 +02:00
uint32_t msg_type ;
2008-05-25 16:26:34 +02:00
DATA_BLOB data ;
PyObject * target ;
NTSTATUS status ;
struct server_id server ;
const char * kwnames [ ] = { " target " , " msg_type " , " data " , NULL } ;
2008-05-30 16:11:07 +10:00
int length ;
2008-05-25 16:26:34 +02:00
2009-11-07 17:57:50 +01:00
if ( ! PyArg_ParseTupleAndKeywords ( args , kwargs , " Ois#:send " ,
2008-05-30 16:11:07 +10:00
discard_const_p ( char * , kwnames ) , & target , & msg_type , & data . data , & length ) ) {
2009-11-07 17:57:50 +01:00
2008-05-25 16:26:34 +02:00
return NULL ;
}
2008-05-30 16:11:07 +10:00
data . length = length ;
2010-09-21 16:08:46 -07:00
if ( ! server_id_from_py ( target , & server ) )
2008-05-25 16:26:34 +02:00
return NULL ;
2011-05-03 10:40:33 +10:00
status = imessaging_send ( iface - > msg_ctx , server , msg_type , & data ) ;
2008-05-25 16:26:34 +02:00
if ( NT_STATUS_IS_ERR ( status ) ) {
PyErr_SetNTSTATUS ( status ) ;
return NULL ;
}
2009-01-06 04:13:57 +01:00
Py_RETURN_NONE ;
2008-05-25 16:26:34 +02:00
}
2011-05-03 10:40:33 +10:00
static void py_msg_callback_wrapper ( struct imessaging_context * msg , void * private_data ,
2008-05-25 16:26:34 +02:00
uint32_t msg_type ,
struct server_id server_id , DATA_BLOB * data )
{
2013-01-26 09:09:23 +11:00
PyObject * py_server_id , * callback = ( PyObject * ) private_data ;
2008-05-25 16:26:34 +02:00
2013-01-26 09:09:23 +11:00
struct server_id * p_server_id = talloc ( NULL , struct server_id ) ;
if ( ! p_server_id ) {
PyErr_NoMemory ( ) ;
return ;
}
* p_server_id = server_id ;
py_server_id = py_return_ndr_struct ( " samba.dcerpc.server_id " , " server_id " , p_server_id , p_server_id ) ;
talloc_unlink ( NULL , p_server_id ) ;
PyObject_CallFunction ( callback , discard_const_p ( char , " i(O)s# " ) , msg_type ,
py_server_id ,
2008-05-25 16:26:34 +02:00
data - > data , data - > length ) ;
}
2011-05-03 10:40:33 +10:00
static PyObject * py_imessaging_register ( PyObject * self , PyObject * args , PyObject * kwargs )
2008-05-25 16:26:34 +02:00
{
2011-05-03 10:40:33 +10:00
imessaging_Object * iface = ( imessaging_Object * ) self ;
2008-05-30 16:19:22 +10:00
int msg_type = - 1 ;
2008-05-25 16:26:34 +02:00
PyObject * callback ;
NTSTATUS status ;
2008-05-26 01:10:24 +02:00
const char * kwnames [ ] = { " callback " , " msg_type " , NULL } ;
2008-05-30 16:19:22 +10:00
2009-11-07 17:57:50 +01:00
if ( ! PyArg_ParseTupleAndKeywords ( args , kwargs , " O|i:register " ,
2008-05-26 01:10:24 +02:00
discard_const_p ( char * , kwnames ) , & callback , & msg_type ) ) {
2008-05-25 16:26:34 +02:00
return NULL ;
}
Py_INCREF ( callback ) ;
2008-05-26 01:10:24 +02:00
if ( msg_type = = - 1 ) {
2008-05-30 16:19:22 +10:00
uint32_t msg_type32 = msg_type ;
2011-05-03 10:40:33 +10:00
status = imessaging_register_tmp ( iface - > msg_ctx , callback ,
2008-05-30 16:19:22 +10:00
py_msg_callback_wrapper , & msg_type32 ) ;
msg_type = msg_type32 ;
2008-05-26 01:10:24 +02:00
} else {
2011-05-03 10:40:33 +10:00
status = imessaging_register ( iface - > msg_ctx , callback ,
2008-05-26 01:10:24 +02:00
msg_type , py_msg_callback_wrapper ) ;
}
2008-05-25 16:26:34 +02:00
if ( NT_STATUS_IS_ERR ( status ) ) {
PyErr_SetNTSTATUS ( status ) ;
return NULL ;
}
2008-05-26 01:10:24 +02:00
return PyLong_FromLong ( msg_type ) ;
2008-05-25 16:26:34 +02:00
}
2011-05-03 10:40:33 +10:00
static PyObject * py_imessaging_deregister ( PyObject * self , PyObject * args , PyObject * kwargs )
2008-05-26 01:15:15 +02:00
{
2011-05-03 10:40:33 +10:00
imessaging_Object * iface = ( imessaging_Object * ) self ;
2008-05-30 16:19:22 +10:00
int msg_type = - 1 ;
2008-05-26 01:15:15 +02:00
PyObject * callback ;
const char * kwnames [ ] = { " callback " , " msg_type " , NULL } ;
2009-11-07 17:57:50 +01:00
if ( ! PyArg_ParseTupleAndKeywords ( args , kwargs , " O|i:deregister " ,
2008-05-26 01:15:15 +02:00
discard_const_p ( char * , kwnames ) , & callback , & msg_type ) ) {
return NULL ;
}
2011-05-03 10:40:33 +10:00
imessaging_deregister ( iface - > msg_ctx , msg_type , callback ) ;
2008-05-26 01:15:15 +02:00
Py_DECREF ( callback ) ;
2009-01-06 04:13:57 +01:00
Py_RETURN_NONE ;
2008-05-26 01:15:15 +02:00
}
2012-10-29 15:34:41 +11:00
static PyObject * py_irpc_servers_byname ( PyObject * self , PyObject * args , PyObject * kwargs )
{
imessaging_Object * iface = ( imessaging_Object * ) self ;
char * server_name ;
2014-07-17 15:05:30 +00:00
unsigned i , num_ids ;
2012-10-29 15:34:41 +11:00
struct server_id * ids ;
PyObject * pylist ;
TALLOC_CTX * mem_ctx = talloc_new ( NULL ) ;
2014-07-17 15:05:30 +00:00
NTSTATUS status ;
2012-10-29 15:34:41 +11:00
if ( ! mem_ctx ) {
PyErr_NoMemory ( ) ;
return NULL ;
}
if ( ! PyArg_ParseTuple ( args , " s " , & server_name ) ) {
TALLOC_FREE ( mem_ctx ) ;
return NULL ;
}
2014-07-17 15:05:30 +00:00
status = irpc_servers_byname ( iface - > msg_ctx , mem_ctx , server_name ,
& num_ids , & ids ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2012-10-29 15:34:41 +11:00
TALLOC_FREE ( mem_ctx ) ;
PyErr_SetString ( PyExc_KeyError , " No such name " ) ;
return NULL ;
}
2014-07-17 15:05:30 +00:00
pylist = PyList_New ( num_ids ) ;
2012-10-29 15:34:41 +11:00
if ( pylist = = NULL ) {
TALLOC_FREE ( mem_ctx ) ;
PyErr_NoMemory ( ) ;
return NULL ;
}
2014-07-17 15:05:30 +00:00
for ( i = 0 ; i < num_ids ; i + + ) {
2012-10-29 15:34:41 +11:00
PyObject * py_server_id ;
struct server_id * p_server_id = talloc ( NULL , struct server_id ) ;
if ( ! p_server_id ) {
PyErr_NoMemory ( ) ;
return NULL ;
}
* p_server_id = ids [ i ] ;
py_server_id = py_return_ndr_struct ( " samba.dcerpc.server_id " , " server_id " , p_server_id , p_server_id ) ;
if ( ! py_server_id ) {
return NULL ;
}
PyList_SetItem ( pylist , i , py_server_id ) ;
talloc_unlink ( NULL , p_server_id ) ;
}
TALLOC_FREE ( mem_ctx ) ;
return pylist ;
}
static PyObject * py_irpc_all_servers ( PyObject * self , PyObject * args , PyObject * kwargs )
{
imessaging_Object * iface = ( imessaging_Object * ) self ;
PyObject * pylist ;
int i ;
struct irpc_name_records * records ;
TALLOC_CTX * mem_ctx = talloc_new ( NULL ) ;
if ( ! mem_ctx ) {
PyErr_NoMemory ( ) ;
return NULL ;
}
records = irpc_all_servers ( iface - > msg_ctx , mem_ctx ) ;
if ( records = = NULL ) {
return NULL ;
}
pylist = PyList_New ( records - > num_records ) ;
if ( pylist = = NULL ) {
TALLOC_FREE ( mem_ctx ) ;
PyErr_NoMemory ( ) ;
return NULL ;
}
for ( i = 0 ; i < records - > num_records ; i + + ) {
PyObject * py_name_record
= py_return_ndr_struct ( " samba.dcerpc.irpc " ,
" name_record " ,
records - > names [ i ] ,
records - > names [ i ] ) ;
if ( ! py_name_record ) {
return NULL ;
}
PyList_SetItem ( pylist , i ,
py_name_record ) ;
}
TALLOC_FREE ( mem_ctx ) ;
return pylist ;
}
2011-05-03 10:40:33 +10:00
static PyMethodDef py_imessaging_methods [ ] = {
{ " send " , ( PyCFunction ) py_imessaging_send , METH_VARARGS | METH_KEYWORDS ,
2008-05-25 16:26:34 +02:00
" S.send(target, msg_type, data) -> None \n Send a message " } ,
2011-05-03 10:40:33 +10:00
{ " register " , ( PyCFunction ) py_imessaging_register , METH_VARARGS | METH_KEYWORDS ,
2008-05-26 01:52:35 +02:00
" S.register(callback, msg_type=None) -> msg_type \n Register a message handler " } ,
2011-05-03 10:40:33 +10:00
{ " deregister " , ( PyCFunction ) py_imessaging_deregister , METH_VARARGS | METH_KEYWORDS ,
2008-05-26 01:52:35 +02:00
" S.deregister(callback, msg_type) -> None \n Deregister a message handler " } ,
2012-10-29 15:34:41 +11:00
{ " irpc_servers_byname " , ( PyCFunction ) py_irpc_servers_byname , METH_VARARGS ,
" S.irpc_servers_byname(name) -> list \n Get list of server_id values that are registered for a particular name " } ,
{ " irpc_all_servers " , ( PyCFunction ) py_irpc_all_servers , METH_NOARGS ,
" S.irpc_servers_byname() -> list \n Get list of all registered names and the associated server_id values " } ,
2008-05-25 16:26:34 +02:00
{ NULL , NULL , 0 , NULL }
} ;
2011-05-03 10:40:33 +10:00
static PyObject * py_imessaging_server_id ( PyObject * obj , void * closure )
2008-05-26 01:52:35 +02:00
{
2011-05-03 10:40:33 +10:00
imessaging_Object * iface = ( imessaging_Object * ) obj ;
2012-10-29 15:33:59 +11:00
PyObject * py_server_id ;
2011-05-03 10:40:33 +10:00
struct server_id server_id = imessaging_get_server_id ( iface - > msg_ctx ) ;
2012-10-29 15:33:59 +11:00
struct server_id * p_server_id = talloc ( NULL , struct server_id ) ;
if ( ! p_server_id ) {
PyErr_NoMemory ( ) ;
return NULL ;
}
* p_server_id = server_id ;
py_server_id = py_return_ndr_struct ( " samba.dcerpc.server_id " , " server_id " , p_server_id , p_server_id ) ;
talloc_unlink ( NULL , p_server_id ) ;
2008-05-26 01:52:35 +02:00
2012-10-29 15:33:59 +11:00
return py_server_id ;
2008-05-26 01:52:35 +02:00
}
2011-05-03 10:40:33 +10:00
static PyGetSetDef py_imessaging_getset [ ] = {
{ discard_const_p ( char , " server_id " ) , py_imessaging_server_id , NULL ,
2008-05-26 01:52:35 +02:00
discard_const_p ( char , " local server id " ) } ,
{ NULL } ,
} ;
2011-05-03 10:40:33 +10:00
PyTypeObject imessaging_Type = {
2008-05-25 16:26:34 +02:00
PyObject_HEAD_INIT ( NULL ) 0 ,
2010-09-21 16:08:46 -07:00
. tp_name = " messaging.Messaging " ,
2011-05-03 10:40:33 +10:00
. tp_basicsize = sizeof ( imessaging_Object ) ,
2008-05-25 16:26:34 +02:00
. tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE ,
2011-05-03 10:40:33 +10:00
. tp_new = py_imessaging_connect ,
. tp_dealloc = py_imessaging_dealloc ,
. tp_methods = py_imessaging_methods ,
. tp_getset = py_imessaging_getset ,
2012-02-06 17:44:34 +11:00
. tp_doc = " Messaging(own_id=None) \n " \
" Create a new object that can be used to communicate with the peers in the specified messaging path. \n "
2008-05-25 16:26:34 +02:00
} ;
2008-05-26 04:14:28 +02:00
void initmessaging ( void )
2008-05-24 18:18:21 +02:00
{
2008-05-24 18:25:27 +02:00
PyObject * mod ;
2008-05-25 16:26:34 +02:00
2011-05-03 10:40:33 +10:00
if ( PyType_Ready ( & imessaging_Type ) < 0 )
2008-05-25 16:26:34 +02:00
return ;
2008-05-26 04:14:28 +02:00
mod = Py_InitModule3 ( " messaging " , NULL , " Internal RPC " ) ;
2008-05-25 16:26:34 +02:00
if ( mod = = NULL )
return ;
2011-05-03 10:40:33 +10:00
Py_INCREF ( ( PyObject * ) & imessaging_Type ) ;
PyModule_AddObject ( mod , " Messaging " , ( PyObject * ) & imessaging_Type ) ;
2008-05-24 18:18:21 +02:00
}