/*
* Copyright (C) 2001, Shilad Sen, Sourcelight Technologies, Inc.
* See xmlrpc.h or the README for more copyright information.
*/
#include <assert.h>
#include <string.h>
#include "xmlrpc.h"
#include "rpcInternal.h"
#ifndef MSWINDOWS
#include <unistd.h>
#endif /* MSWINDOWS */
static PyObject *rpcSourceGetAttr(rpcSource *cp, char *name);
static bool pyMarshaller(
rpcDisp *dp,
rpcSource *srcp,
int actions,
PyObject *params
);
rpcSource *
rpcSourceNew(int fd)
{
rpcSource *sp;
sp = PyObject_NEW(rpcSource, &rpcSourceType);
if (sp == NULL)
return NULL;
sp->fd = fd;
sp->id = -1;
sp->actOcc = 0;
sp->actImp = 0;
sp->desc = NULL;
sp->func = NULL;
sp->params = NULL;
sp->onErrType = ONERR_TYPE_DEF;
sp->onErr = NULL;
sp->doClose = false;
return sp;
}
void
rpcSourceDealloc(rpcSource *srcp)
{
if (srcp->doClose)
close(srcp->fd);
if (srcp->desc) {
free(srcp->desc);
srcp->desc = NULL;
}
if (srcp->params) {
Py_DECREF(srcp->params);
}
if (srcp->onErr and srcp->onErrType == ONERR_TYPE_PY) {
Py_DECREF((PyObject *)srcp->onErr);
}
PyMem_DEL(srcp);
}
void
rpcSourceSetParams(rpcSource *sp, PyObject *params)
{
if (sp->params) {
Py_DECREF(params);
}
sp->params = params;
Py_INCREF(params);
}
void
rpcSourceSetOnErr(rpcSource *srcp, int funcType, void *func)
{
if (srcp->onErrType == ONERR_TYPE_PY and srcp->onErr != NULL) {
Py_DECREF((PyObject *)srcp->onErr);
}
switch (funcType) {
case ONERR_TYPE_DEF:
srcp->onErr = NULL;
break;
case ONERR_TYPE_C:
srcp->onErr = func;
break;
case ONERR_TYPE_PY:
srcp->onErr = func;
Py_INCREF((PyObject *)func);
break;
}
srcp->onErrType = funcType;
}
/*
* Set a handler for errors on the client
*/
static PyObject *
pyRpcSourceSetOnErr(PyObject *self, PyObject *args)
{
PyObject *func;
rpcSource *srcp;
srcp = (rpcSource *)self;
unless (PyArg_ParseTuple(args, "O", &func))
return NULL;
unless (PyCallable_Check(func)) {
PyErr_SetString(rpcError, "error handler must be callable");
return NULL;
}
if (PyObject_Compare(func, Py_None))
rpcSourceSetOnErr(srcp, ONERR_TYPE_PY, func);
else
rpcSourceSetOnErr(srcp, ONERR_TYPE_DEF, NULL);
Py_INCREF(Py_None);
return Py_None;
}
/*
* Get the description associated with the source
*/
static PyObject *
pyRpcSourceGetDesc(PyObject *self, PyObject *args)
{
rpcSource *srcp;
srcp = (rpcSource *)self;
unless (PyArg_ParseTuple(args, ""))
return NULL;
if (srcp->desc)
return PyString_FromString(srcp->desc);
else {
char buff[100];
sprintf(buff, "fd %d", srcp->fd);
return PyString_FromString(buff);
}
return PyInt_FromLong((long)srcp->fd);
}
/*
* Get the description associated with the source
*/
static PyObject *
pyRpcSourceSetDesc(PyObject *self, PyObject *args)
{
rpcSource *srcp;
char *desc;
srcp = (rpcSource *)self;
unless (PyArg_ParseTuple(args, "s", &desc))
return NULL;
if (srcp->desc)
free(srcp->desc);
srcp->desc = alloc(strlen(desc) + 1);
if (srcp->desc == NULL)
return NULL;
strcpy(srcp->desc, desc);
Py_INCREF(Py_None);
return Py_None;
}
/*
* Set the callback for a specific object
*/
static PyObject *
pySetCallback(PyObject *self, PyObject *args)
{
rpcSource *srcp;
int actions;
PyObject *func,
*params,
*realParams;
srcp = (rpcSource *)self;
unless (PyArg_ParseTuple(args, "OiO", &func, &actions, ¶ms))
return NULL;
unless (PyCallable_Check(func))
return setPyErr("Callback must be a callable object");
realParams = Py_BuildValue("(O,O)", func, params);
if (realParams == NULL)
return NULL;
srcp->actImp = actions;
srcp->func = pyMarshaller;
srcp->params = realParams;
Py_INCREF(Py_None);
return Py_None;
}
/*
* Marshall a python callback
*/
static bool
pyMarshaller(rpcDisp *dp, rpcSource *srcp, int acts, PyObject *params)
{
PyObject *res,
*pyFunc,
*realArgs;
assert(PyTuple_Check(params));
assert(PyTuple_GET_SIZE(params) == 2);
pyFunc = PyTuple_GET_ITEM(params, 0);
realArgs = PyTuple_GET_ITEM(params, 1);
assert(PyCallable_Check(pyFunc));
res = PyObject_CallFunction(pyFunc, "(O,i,O)", srcp, acts, realArgs);
if (res == NULL)
return false;
unless (PyInt_Check(res)) {
fprintf(rpcLogger, "callback returned ");
PyObject_Print(res, rpcLogger, 0);
fprintf(rpcLogger, "; removing handler\n");
} else if (PyInt_AsLong(res)) {
srcp->params = params;
srcp->actImp = acts;
srcp->func = pyMarshaller;
Py_INCREF(params);
unless (rpcDispAddSource(dp, srcp))
return false;
}
return true;
}
/*
* member functions for source object
*/
static PyMethodDef rpcSourceMethods[] = {
{ "setOnErr", (PyCFunction)pyRpcSourceSetOnErr, 1, 0 },
{ "getDesc", (PyCFunction)pyRpcSourceGetDesc, 1, 0 },
{ "setDesc", (PyCFunction)pyRpcSourceSetDesc, 1, 0 },
{ "setCallback",(PyCFunction)pySetCallback, 1, 0 },
{ NULL, NULL},
};
/*
* return an attribute for a source object
*/
static PyObject *
rpcSourceGetAttr(rpcSource *cp, char *name)
{
return Py_FindMethod(rpcSourceMethods, (PyObject *)cp, name);
}
/*
* represent an xmlrpc source object
*/
static PyObject *
rpcSourceRepr(rpcSource *srcp)
{
if (srcp->desc) {
PyObject *pystr;
char *buff;
int dlen;
dlen = strlen(srcp->desc);
buff = alloc(dlen + 100 + dlen);
if (buff == NULL)
return NULL;
sprintf(buff, "<xmlrpc Source object, fd %d, %s at %p>",
srcp->fd, srcp->desc, srcp);
pystr = PyString_FromString(buff);
free(buff);
return pystr;
} else {
char buff[100];
sprintf(buff, "<xmlrpc Source object, fd %d, at %p>",
srcp->fd, srcp);
return PyString_FromString(buff);
}
}
/*
* map characterstics of an edb object
*/
PyTypeObject rpcSourceType = {
PyObject_HEAD_INIT(0)
0,
"rpcSource",
sizeof(rpcSource),
0,
(destructor)rpcSourceDealloc, /* tp_dealloc */
0, /* tp_print */
(getattrfunc)rpcSourceGetAttr, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
(reprfunc)rpcSourceRepr, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
0, /* tp_xxx4 */
0, /* tp_doc */
};
syntax highlighted by Code2HTML, v. 0.9.1