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"
2008-10-24 13:13:27 +02:00
# include "scripting/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"
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-02-18 10:10:30 +11:00
# include "librpc/gen_ndr/server_id4.h"
2008-05-24 18:18:21 +02:00
2010-12-29 18:09:09 +01:00
void initmessaging ( void ) ;
2010-11-22 00:07:21 +01:00
extern PyTypeObject messaging_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 ) ) {
PyErr_SetString ( PyExc_ValueError , " Expected tuple " ) ;
return false ;
}
2008-05-26 01:52:35 +02:00
if ( PyTuple_Size ( object ) = = 3 ) {
2011-05-02 10:05:46 +10:00
return PyArg_ParseTuple ( object , " iii " , & server_id - > pid , & server_id - > id2 , & server_id - > node ) ;
2008-05-26 01:52:35 +02:00
} else {
2011-05-02 10:05:46 +10:00
int pid , id2 ;
if ( ! PyArg_ParseTuple ( object , " ii " , & pid , & id2 ) )
2008-05-26 01:52:35 +02:00
return false ;
2011-05-02 10:05:46 +10:00
* server_id = cluster_id ( pid , id2 ) ;
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 ;
struct messaging_context * msg_ctx ;
} messaging_Object ;
2010-12-29 18:56:13 +01:00
static PyObject * py_messaging_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 ;
2008-05-26 01:10:24 +02:00
const char * kwnames [ ] = { " own_id " , " messaging_path " , NULL } ;
PyObject * own_id = Py_None ;
2008-05-25 16:26:34 +02:00
const char * messaging_path = NULL ;
messaging_Object * ret ;
2008-05-26 04:14:28 +02:00
if ( ! PyArg_ParseTupleAndKeywords ( args , kwargs , " |Oz:connect " ,
2008-05-26 01:10:24 +02:00
discard_const_p ( char * , kwnames ) , & own_id , & messaging_path ) ) {
2008-05-25 16:26:34 +02:00
return NULL ;
}
ret = PyObject_New ( messaging_Object , & messaging_Type ) ;
if ( ret = = NULL )
return NULL ;
ret - > mem_ctx = talloc_new ( NULL ) ;
2008-06-14 13:00:53 -04:00
ev = s4_event_context_init ( ret - > mem_ctx ) ;
2008-05-25 16:26:34 +02:00
if ( messaging_path = = NULL ) {
2010-07-16 14:32:42 +10:00
messaging_path = lpcfg_messaging_path ( ret - > mem_ctx ,
2008-11-02 16:50:11 +01:00
py_default_loadparm_context ( ret - > mem_ctx ) ) ;
2008-05-25 16:26:34 +02:00
} else {
messaging_path = talloc_strdup ( ret - > mem_ctx , messaging_path ) ;
}
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 ;
2008-05-25 16:26:34 +02:00
ret - > msg_ctx = messaging_init ( ret - > mem_ctx ,
messaging_path ,
2008-05-26 01:10:24 +02:00
server_id ,
ev ) ;
} else {
ret - > msg_ctx = messaging_client_init ( ret - > mem_ctx ,
messaging_path ,
2008-05-25 16:26:34 +02:00
ev ) ;
}
if ( ret - > msg_ctx = = NULL ) {
PyErr_SetString ( PyExc_RuntimeError , " messaging_connect unable to create a messaging context " ) ;
talloc_free ( ret - > mem_ctx ) ;
return NULL ;
}
return ( PyObject * ) ret ;
}
static void py_messaging_dealloc ( PyObject * self )
{
messaging_Object * iface = ( messaging_Object * ) self ;
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
}
static PyObject * py_messaging_send ( PyObject * self , PyObject * args , PyObject * kwargs )
{
messaging_Object * iface = ( messaging_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 ;
status = messaging_send ( iface - > msg_ctx , server , msg_type , & data ) ;
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
}
2009-02-02 08:20:52 +01:00
static void py_msg_callback_wrapper ( struct messaging_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 )
{
2009-02-02 08:20:52 +01:00
PyObject * callback = ( PyObject * ) private_data ;
2008-05-25 16:26:34 +02:00
PyObject_CallFunction ( callback , discard_const_p ( char , " i(iii)s# " ) , msg_type ,
2011-05-02 10:05:46 +10:00
server_id . pid , server_id . id2 , server_id . node ,
2008-05-25 16:26:34 +02:00
data - > data , data - > length ) ;
}
static PyObject * py_messaging_register ( PyObject * self , PyObject * args , PyObject * kwargs )
{
messaging_Object * iface = ( messaging_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 ;
2008-05-26 01:10:24 +02:00
status = messaging_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 {
status = messaging_register ( iface - > msg_ctx , callback ,
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
}
2008-05-26 01:15:15 +02:00
static PyObject * py_messaging_deregister ( PyObject * self , PyObject * args , PyObject * kwargs )
{
messaging_Object * iface = ( messaging_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 ;
}
messaging_deregister ( iface - > msg_ctx , msg_type , callback ) ;
Py_DECREF ( callback ) ;
2009-01-06 04:13:57 +01:00
Py_RETURN_NONE ;
2008-05-26 01:15:15 +02:00
}
2008-05-25 16:26:34 +02:00
static PyMethodDef py_messaging_methods [ ] = {
{ " send " , ( PyCFunction ) py_messaging_send , METH_VARARGS | METH_KEYWORDS ,
" S.send(target, msg_type, data) -> None \n Send a message " } ,
{ " register " , ( PyCFunction ) py_messaging_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 " } ,
2008-05-26 01:15:15 +02:00
{ " deregister " , ( PyCFunction ) py_messaging_deregister , METH_VARARGS | METH_KEYWORDS ,
2008-05-26 01:52:35 +02:00
" S.deregister(callback, msg_type) -> None \n Deregister a message handler " } ,
2008-05-25 16:26:34 +02:00
{ NULL , NULL , 0 , NULL }
} ;
2008-05-26 01:52:35 +02:00
static PyObject * py_messaging_server_id ( PyObject * obj , void * closure )
{
messaging_Object * iface = ( messaging_Object * ) obj ;
struct server_id server_id = messaging_get_server_id ( iface - > msg_ctx ) ;
2011-05-02 10:05:46 +10:00
return Py_BuildValue ( " (iii) " , server_id . pid , server_id . id2 ,
2008-05-26 01:52:35 +02:00
server_id . node ) ;
}
static PyGetSetDef py_messaging_getset [ ] = {
{ discard_const_p ( char , " server_id " ) , py_messaging_server_id , NULL ,
discard_const_p ( char , " local server id " ) } ,
{ NULL } ,
} ;
2008-05-25 16:26:34 +02:00
PyTypeObject messaging_Type = {
PyObject_HEAD_INIT ( NULL ) 0 ,
2010-09-21 16:08:46 -07:00
. tp_name = " messaging.Messaging " ,
2008-05-25 16:26:34 +02:00
. tp_basicsize = sizeof ( messaging_Object ) ,
. tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE ,
. tp_new = py_messaging_connect ,
. tp_dealloc = py_messaging_dealloc ,
. tp_methods = py_messaging_methods ,
2008-05-26 01:52:35 +02:00
. tp_getset = py_messaging_getset ,
2008-05-26 04:14:28 +02:00
. tp_doc = " Messaging(own_id=None, messaging_path=None) \n " \
" Create a new object that can be used to communicate with the peers in the specified messaging path. \n " \
" If no path is specified, the default path from smb.conf will be used. "
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
if ( PyType_Ready ( & messaging_Type ) < 0 )
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 ;
Py_INCREF ( ( PyObject * ) & messaging_Type ) ;
PyModule_AddObject ( mod , " Messaging " , ( PyObject * ) & messaging_Type ) ;
2008-05-24 18:18:21 +02:00
}