[bind10-dev] Python 2 vs Python 3, was address dependency problems for beta/release
Francis Dupont
fdupont at isc.org
Wed Nov 28 15:04:19 UTC 2012
> - Convert our C++ wrappers from Python 3 to Python 2
=> I did this for the AFTR/PCP (pcp/libpcp/libpcpmodule.c posted below)
It was not very hard, all critical structures and functions got new names
(BTW this avoids misuses, just a bit drastic). Can be funny with generated
interfaces...
IMHO just don't do this!
Regards
Francis Dupont <fdupont at isc.org>
PS: the file:
/*
* Copyright (C) 2011-2012 Internet Systems Consortium, Inc. ("ISC")
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: 511b55cd096f070604b016408614f69d8b4a5ae8 $ */
/*
* PCP (port-control-protocol) client library python module
*
* Francis_Dupont at isc.org, January 2011
*
* a la miniUPnP libnatpmp
*/
#include <Python.h>
#ifdef WIN32
#include <ws2tcpip.h>
#else
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#endif
#include "structmember.h"
#include "pcp.h"
/* for compatibility with Python < 2.4 */
#ifndef Py_RETURN_NONE
#define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None
#endif
#ifndef Py_RETURN_TRUE
#define Py_RETURN_TRUE return Py_INCREF(Py_True), Py_True
#endif
#ifndef Py_RETURN_FALSE
#define Py_RETURN_FALSE return Py_INCREF(Py_False), Py_False
#endif
typedef struct {
PyObject_HEAD
pcp_t pcp;
} PCPObject;
static void
PCPObject_dealloc(PCPObject *self)
{
(void) pcp_close(&self->pcp);
#ifdef Py_TYPE
Py_TYPE(self)->tp_free((PyObject *) self);
#else
self->ob_type->tp_free((PyObject *) self);
#endif
}
/* pcp_init (called open) */
static PyObject *
PCP_open(PyObject *self, PyObject *args, PyObject *kwds)
{
PCPObject *pcp = (PCPObject *) self;
char *server, *source = NULL;
int family = AF_INET, port = 0, ret;
struct sockaddr_in s4, l4;
struct sockaddr_in6 s6, l6;
static char *keywords[] = {"server", "family", "source", "port", 0};
if (!PyArg_ParseTupleAndKeywords(args, kwds,
"s|izi", keywords,
&server, &family, &source, &port))
return NULL;
switch (family) {
case AF_INET:
memset(&s4, 0, sizeof(s4));
s4.sin_family = AF_INET;
if (inet_pton(AF_INET, server, &s4.sin_addr) <= 0)
return Py_BuildValue("i", PCP_ERR_INVAL);
s4.sin_port = htons((unsigned short) port);
if (source != NULL) {
memset(&l4, 0, sizeof(l4));
l4.sin_family = AF_INET;
if (inet_pton(AF_INET, source, &l4.sin_addr) <= 0)
return Py_BuildValue("i", PCP_ERR_INVAL);
ret = pcp_init((struct sockaddr *) &s4,
(struct sockaddr *) &l4,
&pcp->pcp);
} else
ret = pcp_init((struct sockaddr*) &s4,
NULL, &pcp->pcp);
break;
case AF_INET6:
memset(&s6, 0, sizeof(s6));
s6.sin6_family = AF_INET6;
if (inet_pton(AF_INET6, server, &s6.sin6_addr) <= 0)
return Py_BuildValue("i", PCP_ERR_INVAL);
s6.sin6_port = htons((unsigned short) port);
if (source != NULL) {
memset(&l6, 0, sizeof(l6));
l6.sin6_family = AF_INET6;
if (inet_pton(AF_INET6, source, &l6.sin6_addr) <= 0)
return Py_BuildValue("i", PCP_ERR_INVAL);
ret = pcp_init((struct sockaddr *) &s6,
(struct sockaddr *) &l6,
&pcp->pcp);
} else
ret = pcp_init((struct sockaddr*) &s6,
NULL, &pcp->pcp);
break;
default:
return Py_BuildValue("i", PCP_ERR_INVAL);
}
if (ret != PCP_OK) {
PyErr_SetString(PyExc_Exception, pcp_strerror(ret));
return NULL;
}
return Py_BuildValue("i", ret);
}
/* pcp_close */
static PyObject *
PCP_close(PyObject *self)
{
PCPObject *pcp = (PCPObject *) self;
int ret;
ret = pcp_close(&pcp->pcp);
if (ret != PCP_OK) {
PyErr_SetString(PyExc_Exception, pcp_strerror(ret));
return NULL;
}
return Py_BuildValue("i", ret);
}
/* pcp_getsocket */
static PyObject *
PCP_getsocket(PyObject *self)
{
PCPObject *pcp = (PCPObject *) self;
int sock, ret;
ret = pcp_getsocket(&pcp->pcp, &sock);
if (ret < PCP_OK) {
PyErr_SetString(PyExc_Exception, pcp_strerror(ret));
return NULL;
}
return Py_BuildValue("i", sock);
}
/* pcp_setrcsocket */
static PyObject *
PCP_setrcsocket(PyObject *self, PyObject *args)
{
PCPObject *pcp = (PCPObject *) self;
int sock, ret;
if (!PyArg_ParseTuple(args, "i", &sock))
return NULL;
ret = pcp_setrcsocket(&pcp->pcp, sock);
if (ret < PCP_OK) {
PyErr_SetString(PyExc_Exception, pcp_strerror(ret));
return NULL;
}
return Py_BuildValue("i", ret);
}
/* pcp_gettries */
static PyObject *
PCP_gettries(PyObject *self)
{
PCPObject *pcp = (PCPObject *) self;
int trycnt, ret;
ret = pcp_gettries(&pcp->pcp, &trycnt);
if (ret < PCP_OK) {
PyErr_SetString(PyExc_Exception, pcp_strerror(ret));
return NULL;
}
return Py_BuildValue("i", trycnt);
}
/* pcp_gettimeout */
static PyObject *
PCP_gettimeout(PyObject *self, PyObject *args)
{
PCPObject *pcp = (PCPObject *) self;
struct timeval tv;
double d;
int relative, ret;
if (!PyArg_ParseTuple(args, "i", &relative))
return NULL;
ret = pcp_gettimeout(&pcp->pcp, &tv, relative);
if (ret < PCP_OK) {
PyErr_SetString(PyExc_Exception, pcp_strerror(ret));
return NULL;
}
d = (double) tv.tv_sec + (double) tv.tv_usec * .000001;
return Py_BuildValue("d", d);
}
/* pcp_setreset */
static PyObject *
PCP_setreset(PyObject *self, PyObject *args)
{
PCPObject *pcp = (PCPObject *) self;
int reset, old, ret;
if (!PyArg_ParseTuple(args, "i", &reset))
return NULL;
ret = pcp_setreset(&pcp->pcp, reset, &old);
if (ret < PCP_OK) {
PyErr_SetString(PyExc_Exception, pcp_strerror(ret));
return NULL;
}
return Py_BuildValue("i", old);
}
/* pcp_setautofill */
static PyObject *
PCP_setautofill(PyObject *self, PyObject *args)
{
PCPObject *pcp = (PCPObject *) self;
int autofill, old, ret;
if (!PyArg_ParseTuple(args, "i", &autofill))
return NULL;
ret = pcp_setautofill(&pcp->pcp, autofill, &old);
if (ret < PCP_OK) {
PyErr_SetString(PyExc_Exception, pcp_strerror(ret));
return NULL;
}
return Py_BuildValue("i", old);
}
/* pcp_third_party */
static PyObject *
PCP_third_party(PyObject *self, PyObject *args)
{
char *addr = NULL;
int family = 0;
uint8_t a[16];
self = self;
if (!PyArg_ParseTuple(args, "|is", &family, &addr))
return NULL;
if (addr == NULL)
return Py_BuildValue("i", PCP_ERR_INVAL);
switch (family) {
case AF_INET:
memcpy(a, pcp_mapped, 12);
if (inet_pton(AF_INET, addr, a + 12) <= 0)
return Py_BuildValue("i", PCP_ERR_INVAL);
break;
case AF_INET6:
if (inet_pton(AF_INET6, addr, a) <= 0)
return Py_BuildValue("i", PCP_ERR_INVAL);
break;
default:
return Py_BuildValue("i", PCP_ERR_INVAL);
}
#if PY_MAJOR_VERSION == 2
return Py_BuildValue("is#", PCP_OPTION_THIRD_PARTY,
a, PCP_LEN_OPT3PTY);
#else
return Py_BuildValue("iy#", PCP_OPTION_THIRD_PARTY,
a, PCP_LEN_OPT3PTY);
#endif
}
/* pcp_prefer_failure */
static PyObject *
PCP_prefer_failure(PyObject *self)
{
self = self;
#if PY_MAJOR_VERSION == 2
return Py_BuildValue("is#", PCP_OPTION_PREF_FAIL, (uint8_t *) "", 0);
#else
return Py_BuildValue("iy#", PCP_OPTION_PREF_FAIL, (uint8_t *) "", 0);
#endif
}
/* pcp_filter */
static PyObject *
PCP_filter(PyObject *self, PyObject *args)
{
char *addr;
int family, prefixlen, port;
uint16_t n16;
uint8_t val[20];
self = self;
if (!PyArg_ParseTuple(args, "iisi", &family, &prefixlen, &addr, &port))
return NULL;
val[PCP_OPTDFLT_RSVD] = 0;
val[PCP_OPTDFLT_PLEN] = (uint8_t) prefixlen;
n16 = htons((uint16_t) port);
memcpy(val + PCP_OPTDFLT_PORT, &n16, 2);
switch (family) {
case AF_INET:
val[PCP_OPTDFLT_PLEN] += 96;
memcpy(val + PCP_OPTDFLT_PREF, pcp_mapped, 12);
if (inet_pton(AF_INET, addr,
val + 12 + PCP_OPTDFLT_PREF) <= 0)
return Py_BuildValue("i", PCP_ERR_INVAL);
break;
case AF_INET6:
if (inet_pton(AF_INET6, addr,
val + PCP_OPTDFLT_PREF) <= 0)
return Py_BuildValue("i", PCP_ERR_INVAL);
break;
default:
return Py_BuildValue("i", PCP_ERR_INVAL);
}
#if PY_MAJOR_VERSION == 2
return Py_BuildValue("is#", PCP_OPTION_FILTER,
val, PCP_LEN_OPTFLT);
#else
return Py_BuildValue("iy#", PCP_OPTION_FILTER,
val, PCP_LEN_OPTFLT);
#endif
}
/* parse request */
static int
parse_request(pcp_request_t *req, pcp_option_t ***options,
PyObject *args, PyObject *kwds)
{
PyObject *poptions = NULL, *po, *v;
static pcp_option_t o[PCP_VECOPT_SIZE], *t[PCP_VECOPT_SIZE];
char *intaddr = NULL, *extaddr = NULL, *remotepeer = NULL;
int opcode = PCP_OPCODE_MAP, protocol = 0;
int lifetime = 0, intport = 0, extport = 0, peerport = 0, len, i;
static char *keywords[] = {"opcode", "lifetime", "protocol",
"intaddr", "extaddr", "remotepeer",
"intport", "extport", "peerport",
"options", 0 };
if (!PyArg_ParseTupleAndKeywords(args, kwds,
"|iiizzziiiO", keywords,
&opcode, &lifetime, &protocol,
&intaddr, &extaddr, &remotepeer,
&intport, &extport, &peerport,
&poptions))
return PCP_ERR_APP0;
memset(req, 0, sizeof(*req));
memset(o, 0, sizeof(o));
memset(t, 0, sizeof(t));
req->opcode = opcode;
req->protocol = protocol;
req->lifetime = lifetime;
if (intaddr != NULL) {
if (strchr(intaddr, ':') == NULL) {
if (inet_pton(AF_INET, intaddr, &req->intaddr4) <= 0)
return PCP_ERR_INVAL;
pcp_mapintaddr(req);
} else if (inet_pton(AF_INET6, intaddr, req->intaddr6) <= 0)
return PCP_ERR_INVAL;
}
req->intport = intport;
if (extaddr != NULL) {
if (strchr(extaddr, ':') == NULL) {
if (inet_pton(AF_INET, extaddr, &req->extaddr4) <= 0)
return PCP_ERR_INVAL;
pcp_mapextaddr(req);
} else if (inet_pton(AF_INET6, extaddr, req->extaddr6) <= 0)
return PCP_ERR_INVAL;
}
req->extport = extport;
if (opcode == PCP_OPCODE_PEER) {
if (remotepeer != NULL) {
if (strchr(remotepeer, ':') == NULL) {
if (inet_pton(AF_INET,
remotepeer,
&req->remotepeer4) <= 0)
return PCP_ERR_INVAL;
pcp_mapremotepeer(req);
} else if (inet_pton(AF_INET6,
remotepeer,
req->remotepeer6) <= 0)
return PCP_ERR_INVAL;
}
req->peerport = peerport;
}
if (poptions == NULL)
return PCP_OK;
if (!PyList_Check(poptions)) {
PyErr_SetString(PyExc_TypeError, "options is not a list");
return PCP_ERR_APP0;
}
len = PyList_Size(poptions);
if (len > PCP_MAX_OPTIONS) {
PyErr_SetString(PyExc_ValueError, "too many options");
return PCP_ERR_APP0;
}
for (i = 0; i < len; i++) {
po = PyList_GetItem(poptions, i);
if (po == NULL)
return PCP_ERR_APP0;
if (!PyTuple_Check(po) || (PyTuple_Size(po) != 2)) {
err:
PyErr_SetString(PyExc_ValueError,
"bad tuple in options");
return PCP_ERR_APP0;
}
v = PyTuple_GetItem(po, 0);
#if PY_MAJOR_VERSION == 2
if ((v == NULL) || !PyInt_Check(v))
goto err;
o[i].code = (int) PyInt_AsLong(v);
#else
if ((v == NULL) || !PyLong_Check(v))
goto err;
o[i].code = (int) PyLong_AsLong(v);
#endif
v = PyTuple_GetItem(po, 1);
#if PY_MAJOR_VERSION == 2
if ((v == NULL) || !PyString_Check(v))
goto err;
o[i].data = (uint8_t *) PyString_AsString(v);
o[i].length = (uint16_t) PyString_Size(v);
#else
if ((v == NULL) || !PyBytes_Check(v))
goto err;
o[i].data = (uint8_t *) PyBytes_AsString(v);
o[i].length = (uint16_t) PyBytes_Size(v);
#endif
t[i] = &o[i];
}
*options = t;
return PCP_OK;
}
/* pcp_makerequest */
static PyObject *
PCP_makerequest(PyObject *self, PyObject *args, PyObject *kwds)
{
PCPObject *pcp = (PCPObject *) self;
pcp_request_t req;
pcp_option_t **options = NULL;
int ret;
ret = parse_request(&req, &options, args, kwds);
if (ret < PCP_OK) {
if (ret == PCP_ERR_APP0)
return NULL;
return Py_BuildValue("i", ret);
}
ret = pcp_makerequest(&pcp->pcp, &req, options);
if (ret < PCP_OK) {
PyErr_SetString(PyExc_Exception, pcp_strerror(ret));
return NULL;
}
return Py_BuildValue("i", ret);
}
/* pcp_sendrequest */
static PyObject *
PCP_sendrequest(PyObject *self)
{
PCPObject *pcp = (PCPObject *) self;
int ret;
ret = pcp_sendrequest(&pcp->pcp);
if (ret < PCP_OK) {
PyErr_SetString(PyExc_Exception, pcp_strerror(ret));
return NULL;
}
return Py_BuildValue("i", ret);
}
/* build response */
static PyObject *
build_response(pcp_response_t *resp)
{
PyObject *options, *po;
pcp_option_t *o;
char intaddr[INET6_ADDRSTRLEN];
char extaddr[INET6_ADDRSTRLEN];
char remotepeer[INET6_ADDRSTRLEN];
int i, announce = 0, peer = 0;
switch (resp->assigned.opcode) {
case PCP_OPCODE_ANNOUNCE | PCP_OPCODE_RESPONSE:
announce = 1;
break;
case PCP_OPCODE_MAP | PCP_OPCODE_RESPONSE:
if (pcp_unmapextaddr(&resp->assigned)) {
if (inet_ntop(AF_INET, &resp->assigned.extaddr4,
extaddr, sizeof(extaddr)) == NULL)
return NULL;
} else if (inet_ntop(AF_INET6, resp->assigned.extaddr6,
extaddr, sizeof(extaddr)) == NULL)
return NULL;
break;
case PCP_OPCODE_PEER | PCP_OPCODE_RESPONSE:
if (pcp_unmapremotepeer(&resp->assigned)) {
if (inet_ntop(AF_INET, &resp->assigned.remotepeer4,
remotepeer, sizeof(extaddr)) == NULL)
return NULL;
} else if (inet_ntop(AF_INET6, resp->assigned.remotepeer6,
remotepeer, sizeof(extaddr)) == NULL)
return NULL;
if (pcp_unmapextaddr(&resp->assigned)) {
if (inet_ntop(AF_INET, &resp->assigned.extaddr4,
extaddr, sizeof(extaddr)) == NULL)
return NULL;
} else if (inet_ntop(AF_INET6, resp->assigned.extaddr6,
extaddr, sizeof(extaddr)) == NULL)
return NULL;
peer = 1;
break;
default:
return NULL;
}
options = PyList_New(0);
for (i = 0; i < resp->optcnt; i++) {
o = &resp->options[i];
#if PY_MAJOR_VERSION == 2
po = Py_BuildValue("is#", o->code,
o->data == NULL ? (uint8_t *) "" : o->data,
o->length);
#else
po = Py_BuildValue("iy#", o->code,
o->data == NULL ? (uint8_t *) "" : o->data,
o->length);
#endif
if (PyList_Append(options, po)) {
Py_XDECREF(po);
Py_XDECREF(options);
return NULL;
}
Py_XDECREF(po);
}
if (announce)
return Py_BuildValue(
"{s:i,s:i,s:i,s:O}",
"result", resp->result,
"epoch", resp->epoch,
"opcode", resp->assigned.opcode,
"options", options);
else if (!peer)
return Py_BuildValue(
"{s:i,s:i,s:i,s:i,s:s,s:s,s:i,s:i,s:i,s:O}",
"result", resp->result,
"epoch", resp->epoch,
"opcode", resp->assigned.opcode,
"protocol", resp->assigned.protocol,
"intaddr", intaddr,
"extaddr", extaddr,
"lifetime", resp->assigned.lifetime,
"intport", resp->assigned.intport,
"extport", resp->assigned.extport,
"options", options);
else
return Py_BuildValue(
"{s:i,s:i,s:i,s:i,s:s,s:s,s:s,s:i,s:i,s:i,s:i,s:O}",
"result", resp->result,
"epoch", resp->epoch,
"opcode", resp->assigned.opcode,
"protocol", resp->assigned.protocol,
"intaddr", intaddr,
"extaddr", extaddr,
"remotepeer", remotepeer,
"lifetime", resp->assigned.lifetime,
"intport", resp->assigned.intport,
"extport", resp->assigned.extport,
"peerport", resp->assigned.peerport,
"options", options);
}
/* pcp_recvresponse */
static PyObject *
PCP_recvresponse(PyObject *self)
{
PCPObject *pcp = (PCPObject *) self;
PyObject *tmp = NULL;
pcp_response_t resp;
int ret;
memset(&resp, 0, sizeof(resp));
ret = pcp_recvresponse(&pcp->pcp, &resp);
if (ret < PCP_OK) {
PyErr_SetString(PyExc_Exception, pcp_strerror(ret));
return NULL;
}
if (ret == PCP_OK)
tmp = build_response(&resp);
if (tmp == NULL)
return Py_BuildValue("i{}", ret);
else
return Py_BuildValue("iN", ret, tmp);
}
/* pcp_getmapping */
static PyObject *
PCP_getmapping(PyObject *self, PyObject *args, PyObject *kwds)
{
PCPObject *pcp = (PCPObject *) self;
PyObject *tmp = NULL;
pcp_request_t req;
pcp_option_t **options = NULL;
pcp_response_t resp;
int ret;
ret = parse_request(&req, &options, args, kwds);
if (ret < PCP_OK) {
if (ret == PCP_ERR_APP0)
return NULL;
return Py_BuildValue("i", ret);
}
memset(&resp, 0, sizeof(resp));
ret = pcp_getmapping(&pcp->pcp, &req, options, &resp);
if (ret < PCP_OK) {
PyErr_SetString(PyExc_Exception, pcp_strerror(ret));
return NULL;
}
if (ret == PCP_OK)
tmp = build_response(&resp);
if (tmp == NULL)
return Py_BuildValue("i{}", ret);
else
return Py_BuildValue("iN", ret, tmp);
}
/* pcp_renewmapping */
static PyObject *
PCP_renewmapping(PyObject *self)
{
PCPObject *pcp = (PCPObject *) self;
PyObject *tmp = NULL;
pcp_response_t resp;
int ret;
memset(&resp, 0, sizeof(resp));
ret = pcp_renewmapping(&pcp->pcp, &resp);
if (ret < PCP_OK) {
PyErr_SetString(PyExc_Exception, pcp_strerror(ret));
return NULL;
}
if (ret == PCP_OK)
tmp = build_response(&resp);
if (tmp == NULL)
return Py_BuildValue("i{}", ret);
else
return Py_BuildValue("iN", ret, tmp);
}
/* pcp_delmapping */
static PyObject *
PCP_delmapping(PyObject *self)
{
PCPObject *pcp = (PCPObject *) self;
PyObject *tmp = NULL;
pcp_response_t resp;
int ret;
memset(&resp, 0, sizeof(resp));
ret = pcp_delmapping(&pcp->pcp, &resp);
if (ret < PCP_OK) {
PyErr_SetString(PyExc_Exception, pcp_strerror(ret));
return NULL;
}
if (ret == PCP_OK)
tmp = build_response(&resp);
if (tmp == NULL)
return Py_BuildValue("i{}", ret);
else
return Py_BuildValue("iN", ret, tmp);
}
/* _pcp_fdinit */
static PyObject *
PCP_fdopen(PyObject *self, PyObject *args)
{
PCPObject *pcp = (PCPObject *) self;
int fd, ret;
if (!PyArg_ParseTuple(args, "i", &fd))
return NULL;
ret = _pcp_fdinit(&pcp->pcp, fd);
if (ret != PCP_OK) {
PyErr_SetString(PyExc_Exception, pcp_strerror(ret));
return NULL;
}
return Py_BuildValue("i", ret);
}
/* _pcp_setrequest */
static PyObject *
PCP_setrequest(PyObject *self, PyObject *args)
{
PCPObject *pcp = (PCPObject *) self;
uint8_t *req = NULL;
int len, ret;
#if PY_MAJOR_VERSION == 2
if (!PyArg_ParseTuple(args, "s#", &req, &len))
return NULL;
#else
if (!PyArg_ParseTuple(args, "y#", &req, &len))
return NULL;
#endif
ret = _pcp_setrequest(&pcp->pcp, req, (uint16_t) len);
if (ret < PCP_OK) {
PyErr_SetString(PyExc_Exception, pcp_strerror(ret));
return NULL;
}
return Py_BuildValue("i", ret);
}
/* _pcp_getrequest */
static PyObject *
PCP_getrequest(PyObject *self)
{
PCPObject *pcp = (PCPObject *) self;
uint8_t *req = NULL;
uint16_t len;
int ret;
ret = _pcp_getrequest(&pcp->pcp, &req, &len);
if (ret < PCP_OK) {
PyErr_SetString(PyExc_Exception, pcp_strerror(ret));
return NULL;
}
#if PY_MAJOR_VERSION == 2
return Py_BuildValue("s#", req, (int) len);
#else
return Py_BuildValue("y#", req, (int) len);
#endif
}
/* _pcp_setresponse */
static PyObject *
PCP_setresponse(PyObject *self, PyObject *args)
{
PCPObject *pcp = (PCPObject *) self;
uint8_t *resp = NULL;
int len, ret;
#if PY_MAJOR_VERSION == 2
if (!PyArg_ParseTuple(args, "s#", &resp, &len))
return NULL;
#else
if (!PyArg_ParseTuple(args, "y#", &resp, &len))
return NULL;
#endif
ret = _pcp_setresponse(&pcp->pcp, resp, (uint16_t) len);
if (ret < PCP_OK) {
PyErr_SetString(PyExc_Exception, pcp_strerror(ret));
return NULL;
}
return Py_BuildValue("i", ret);
}
/* _pcp_getresponse */
static PyObject *
PCP_getresponse(PyObject *self)
{
PCPObject *pcp = (PCPObject *) self;
uint8_t *resp = NULL;
uint16_t len;
int ret;
ret = _pcp_getresponse(&pcp->pcp, &resp, &len);
if (ret < PCP_OK) {
PyErr_SetString(PyExc_Exception, pcp_strerror(ret));
return NULL;
}
#if PY_MAJOR_VERSION == 2
return Py_BuildValue("s#", resp, (int) len);
#else
return Py_BuildValue("y#", resp, (int) len);
#endif
}
/* _pcp_submitresponse */
static PyObject *
PCP_submitresponse(PyObject *self)
{
PCPObject *pcp = (PCPObject *) self;
PyObject *tmp = NULL;
pcp_response_t resp;
int ret;
memset(&resp, 0, sizeof(resp));
ret = _pcp_submitresponse(&pcp->pcp, &resp);
if (ret < PCP_OK) {
PyErr_SetString(PyExc_Exception, pcp_strerror(ret));
return NULL;
}
if (ret == PCP_OK)
tmp = build_response(&resp);
if (tmp == NULL)
return Py_BuildValue("i{}", ret);
else
return Py_BuildValue("iN", ret, tmp);
}
static PyObject *
PCP_getoptinfo(PyObject *self, PyObject *args)
{
uint8_t *odata;
char buf[256];
int code, len, isv4;
size_t done;
uint16_t n16;
self = self;
#if PY_MAJOR_VERSION == 2
if (!PyArg_ParseTuple(args, "is#", &code, &odata, &len))
return NULL;
#else
if (!PyArg_ParseTuple(args, "iy#", &code, &odata, &len))
return NULL;
#endif
memset(buf, 0, sizeof(buf));
switch (code) {
case PCP_OPTION_THIRD_PARTY:
if (len == PCP_LEN_OPT0) {
(void) snprintf(buf, sizeof(buf), "all");
break;
}
if (len != PCP_LEN_OPT3PTY)
Py_RETURN_NONE;
if (memcmp(odata, pcp_mapped, 12) == 0)
(void) inet_ntop(AF_INET, odata + 12,
buf, sizeof(buf));
else
(void) inet_ntop(AF_INET6, odata,
buf, sizeof(buf));
break;
case PCP_OPTION_PREF_FAIL:
if (len != PCP_LEN_OPT0)
Py_RETURN_NONE;
break;
case PCP_OPTION_FILTER:
if (len != PCP_LEN_OPTFLT)
Py_RETURN_NONE;
if ((odata[1] >= 96) &&
(memcmp(odata + PCP_OPTDFLT_PREF, pcp_mapped, 12) == 0)) {
isv4 = 1;
(void) inet_ntop(AF_INET,
odata + 12 + PCP_OPTDFLT_PREF,
buf, sizeof(buf));
} else {
isv4 = 0;
(void) inet_ntop(AF_INET6,
odata + PCP_OPTDFLT_PREF,
buf, sizeof(buf));
}
memcpy(&n16, odata + PCP_OPTDFLT_PORT, 2);
n16 = ntohs(n16);
done = strlen(buf);
(void) snprintf(buf + done, sizeof(buf) - done, "/%d %hu",
(int) isv4 ? odata[1] - 96 : odata[1], n16);
break;
default:
Py_RETURN_NONE;
}
return Py_BuildValue("s", buf);
}
/* Method Table */
static PyMethodDef PCPObject_methods[] = {
{ "open", (PyCFunction) PCP_open, METH_VARARGS | METH_KEYWORDS,
"open(server, [family:, source:, port:]) -> pcp_init" },
{ "close", (PyCFunction) PCP_close, METH_NOARGS,
"close() -> pcp_close" },
{ "getsocket", (PyCFunction) PCP_getsocket, METH_NOARGS,
"getsocket() -> pcp_getsocket (err<0 or socket)" },
{ "setrcsocket", (PyCFunction) PCP_setrcsocket, METH_VARARGS,
"setrcsocket(sock) -> pcp_setrcsocket" },
{ "gettries", (PyCFunction) PCP_gettries, METH_NOARGS,
"gettries() -> pcp_gettries (err<0 or socket)" },
{ "gettimeout", (PyCFunction) PCP_gettimeout, METH_VARARGS,
"gettimeout(relative) -> pcp_gettimeout (tv_sec, tv_usec)" },
{ "setreset", (PyCFunction) PCP_setreset, METH_VARARGS,
"setreset(reset) -> pcp_setreset (old)" },
{ "setautofill", (PyCFunction) PCP_setautofill, METH_VARARGS,
"setautofill(autofill) -> pcp_setautofill (old)" },
{ "third_party", (PyCFunction) PCP_third_party, METH_VARARGS,
"third_party(family, address) -> pcp_third_party" },
{ "prefer_failure", (PyCFunction) PCP_prefer_failure, METH_NOARGS,
"prefer_failure() -> pcp_prefer_failure" },
{ "filter", (PyCFunction) PCP_filter, METH_VARARGS,
"filter(family, address, port) -> pcp_filter" },
{ "makerequest", (PyCFunction) PCP_makerequest,
METH_VARARGS | METH_KEYWORDS,
"makerequest([opcode:, protocol:, [int|ext]addr:, lifetime:, \n"
"[int|ext]port:, options]) -> pcp_makerequest" },
{ "sendrequest", (PyCFunction) PCP_sendrequest, METH_NOARGS,
"sendrequest() -> pcp_sendrequest" },
{ "recvresponse", (PyCFunction) PCP_recvresponse, METH_NOARGS,
"recvresponse() -> pcp_recvresponse {dict}" },
{ "getmapping", (PyCFunction) PCP_getmapping,
METH_VARARGS | METH_KEYWORDS,
"getmapping([opcode:, protocol:, [int|ext]addr:, lifetime:, \n"
"[int|ext]port:, options]) -> pcp_getmapping {dict}" },
{ "renewmapping", (PyCFunction) PCP_renewmapping, METH_NOARGS,
"renewmapping() -> pcp_renewmapping {dict}" },
{ "delmapping", (PyCFunction) PCP_delmapping, METH_NOARGS,
"delmapping() -> pcp_delmapping {dict}" },
{ "fdopen", (PyCFunction) PCP_fdopen, METH_VARARGS,
"fdopen(fd) -> _pcp_fdinit" },
{ "setrequest", (PyCFunction) PCP_setrequest, METH_VARARGS,
"setrequest('req') -> _pcp_setrequest" },
{ "getrequest", (PyCFunction) PCP_getrequest, METH_NOARGS,
"getrequest() -> _pcp_getrequest" },
{ "setresponse", (PyCFunction) PCP_setresponse, METH_VARARGS,
"setresponse('req') -> _pcp_setresponse" },
{ "getresponse", (PyCFunction) PCP_getresponse, METH_NOARGS,
"getresponse() -> _pcp_getresponse" },
{ "submitresponse", (PyCFunction) PCP_submitresponse, METH_NOARGS,
"submitresponse() -> pcp_submitresponse {dict}" },
{ "getoptinfo", (PyCFunction) PCP_getoptinfo, METH_VARARGS,
"getoptinfo() -> option info" },
{ NULL, NULL, 0, NULL }
};
static PyTypeObject PCPType = {
#if PY_MAJOR_VERSION == 2
PyObject_HEAD_INIT(NULL)
0, /* ob_size */
#else
PyVarObject_HEAD_INIT(NULL, 0)
#endif
"libpcp.PCP", /* tp_name */
sizeof(PCPObject), /* tp_basicsize */
0, /* tp_itemsize */
(destructor) PCPObject_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* 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 */
Py_TPFLAGS_DEFAULT, /* tp_flags */
"PCP objects", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
PCPObject_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
0, /* tp_new */
0, /* tp_free */
};
#if PY_MAJOR_VERSION == 2
/* module methods */
static PyMethodDef libpcp_methods[] = {
{ NULL, NULL, 0, NULL }
};
#else
/* module definition */
static PyModuleDef libpcp_module = {
PyModuleDef_HEAD_INIT,
"libpcp", /* m_name */
"PCP client library", /* m_doc */
-1, /* m_size */
NULL, /* m_methods */
NULL, /* m_reload */
NULL, /* m_traverse */
NULL, /* m_clear */
NULL /* m_free */
};
#endif
#ifndef PyMODINIT_FUNC
#define PyMODINIT_FUNC void
#endif
PyMODINIT_FUNC
#if PY_MAJOR_VERSION == 2
initlibpcp(void)
#else
PyInit_libpcp(void)
#endif
{
PyObject *mod;
PCPType.tp_new = PyType_GenericNew;
#if PY_MAJOR_VERSION == 2
if (PyType_Ready(&PCPType) < 0)
return;
#else
if (PyType_Ready(&PCPType) < 0)
return NULL;
#endif
#if PY_MAJOR_VERSION == 2
mod = Py_InitModule3("libpcp",
libpcp_methods,
"PCP client library.");
if (mod == NULL)
return;
#else
mod = PyModule_Create(&libpcp_module);
if (mod == NULL)
return NULL;
#endif
Py_INCREF(&PCPType);
PyModule_AddObject(mod, "PCP", (PyObject *) &PCPType);
PyModule_AddIntConstant(mod, "PORT", PCP_PORT);
PyModule_AddIntConstant(mod, "RC_PORT", PCP_RC_PORT);
PyModule_AddIntConstant(mod, "OPCODE_ANNOUNCE", PCP_OPCODE_ANNOUNCE);
PyModule_AddIntConstant(mod, "OPCODE_MAP", PCP_OPCODE_MAP);
PyModule_AddIntConstant(mod, "OPCODE_PEER", PCP_OPCODE_PEER);
PyModule_AddIntConstant(mod, "OPCODE_RESPONSE", PCP_OPCODE_RESPONSE);
PyModule_AddIntConstant(mod, "OK", PCP_OK);
PyModule_AddIntConstant(mod, "TRY_AGAIN", PCP_TRY_AGAIN);
PyModule_AddIntConstant(mod, "ERR_INVAL", PCP_ERR_INVAL);
PyModule_AddIntConstant(mod, "ERR_NOMEM", PCP_ERR_NOMEM);
PyModule_AddIntConstant(mod, "ERR_SOCKET", PCP_ERR_SOCKET);
PyModule_AddIntConstant(mod, "ERR_BIND", PCP_ERR_BIND);
PyModule_AddIntConstant(mod, "ERR_CONNECT", PCP_ERR_CONNECT);
PyModule_AddIntConstant(mod, "ERR_SEND", PCP_ERR_SEND);
PyModule_AddIntConstant(mod, "ERR_RECV", PCP_ERR_RECV);
PyModule_AddIntConstant(mod, "ERR_SYSCALL", PCP_ERR_SYSCALL);
PyModule_AddIntConstant(mod, "ERR_NOREQUEST", PCP_ERR_NOREQUEST);
PyModule_AddIntConstant(mod, "ERR_RECVBAD", PCP_ERR_RECVBAD);
PyModule_AddIntConstant(mod, "ERR_TOOMANYOPTS", PCP_ERR_TOOMANYOPTS);
PyModule_AddIntConstant(mod, "ERR_FAILURE", PCP_ERR_FAILURE);
PyModule_AddIntConstant(mod, "ERR_APP0", PCP_ERR_APP0);
PyModule_AddIntConstant(mod, "ERR_APP1", PCP_ERR_APP1);
PyModule_AddIntConstant(mod, "ERR_APP2", PCP_ERR_APP2);
PyModule_AddIntConstant(mod, "ERR_PROTOBASE", PCP_ERR_PROTOBASE);
PyModule_AddIntConstant(mod, "ERR_UNSUPVERSION", PCP_ERR_UNSUPVERSION);
PyModule_AddIntConstant(mod, "ERR_NOTAUTH", PCP_ERR_NOTAUTH);
PyModule_AddIntConstant(mod, "ERR_BADREQUEST", PCP_ERR_BADREQUEST);
PyModule_AddIntConstant(mod, "ERR_UNSUPOPCODE", PCP_ERR_UNSUPOPCODE);
PyModule_AddIntConstant(mod, "ERR_UNSUPOPTION", PCP_ERR_UNSUPOPTION);
PyModule_AddIntConstant(mod, "ERR_BADOPTION", PCP_ERR_BADOPTION);
PyModule_AddIntConstant(mod, "ERR_NETFAILURE", PCP_ERR_NETFAILURE);
PyModule_AddIntConstant(mod, "ERR_NORESOURCES", PCP_ERR_NORESOURCES);
PyModule_AddIntConstant(mod, "ERR_UNSUPPROTO", PCP_ERR_UNSUPPROTO);
PyModule_AddIntConstant(mod, "ERR_EXQUOTA", PCP_ERR_EXQUOTA);
PyModule_AddIntConstant(mod, "ERR_CANTPROVIDE", PCP_ERR_CANTPROVIDE);
PyModule_AddIntConstant(mod, "ERR_ADDRMISMATCH", PCP_ERR_ADDRMISMATCH);
PyModule_AddIntConstant(mod, "ERR_TOOMANYPEER", PCP_ERR_TOOMANYPEER);
PyModule_AddIntConstant(mod, "ERR_PROCERROR", PCP_ERR_PROCERROR);
PyModule_AddIntConstant(mod, "OPTION_FILTER", PCP_OPTION_FILTER);
PyModule_AddIntConstant(mod, "OPTION_PREF_FAIL", PCP_OPTION_PREF_FAIL);
PyModule_AddIntConstant(mod, "OPTION_THIRD_PARTY",
PCP_OPTION_THIRD_PARTY);
PyModule_AddIntConstant(mod, "MAX_TRIES", PCP_MAX_TRIES);
PyModule_AddIntConstant(mod, "MAX_TIMEOUT", PCP_MAX_TIMEOUT);
#if PY_MAJOR_VERSION > 2
return mod;
#endif
}
More information about the bind10-dev
mailing list