Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
oai
freediameter
Commits
0c11a767
Commit
0c11a767
authored
Dec 20, 2010
by
Sebastien Decugis
Browse files
dbg_interactive almost complete
parent
30d8181e
Changes
12
Hide whitespace changes
Inline
Side-by-side
doc/dbg_interactive.py.sample
View file @
0c11a767
...
...
@@ -89,7 +89,7 @@ l3.insert_next(l4) # l3 -> l4
l3.insert_next(l5) # l3 -> l5 -> l4
l1.concat(l3) # l1 -> l2 -> l5 -> l4
elements = l1.enum_as() # default: enumerates as fd_list. Warning: this a copy, changing the python list has no effect on the underlying list.
elements = l1.enum_as() # default: enumerates as fd_list. Warning: this a copy, changing the python list has no effect on the underlying
fd_
list.
for li in elements:
li.dump()
...
...
@@ -223,9 +223,6 @@ d.new_obj(DICT_RULE, r, my_req)
d.new_obj(DICT_RULE, r, my_ans)
del r
d.dump()
del d
r2 = dict_rule_data(my_avp_int, RULE_REQUIRED) # min & max are optional parameters, default to -1
r3 = dict_rule_data(my_avp_int, RULE_REQUIRED, 2, 3) # min is 2, max is 3
r4 = dict_rule_data(my_avp_int, RULE_FIXED_HEAD) # The r4.rule_order = 1 by default, change afterwards if needed.
...
...
@@ -233,6 +230,9 @@ del r2
del r3
del r4
d.dump()
del d
####### Now play with the "real" dictionary
gdict = cvar.fd_g_config.cnf_dict
...
...
@@ -272,7 +272,7 @@ hdl = session_handler(my_cleanup)
s1 = session()
s1.getsid()
s2 = session("this.is.a.full.session.id")
r,s3,isnew = fd_sess_fromsid("this.is.a.full.session.id")
r,s3,isnew = fd_sess_fromsid("this.is.a.full.session.id")
# use this call if "isnew" is really needed...
s4 = session("host.id", "optional.part")
s4.settimeout(30) # the python wrapper takes a number of seconds as parameter for simplicity
s4.dump()
...
...
@@ -303,6 +303,31 @@ list = rd.extract(-1)
for c in list.enum_as("struct rtd_candidate *"):
print "%s (%s): %s" % (c.diamid, c.realm, c.score)
del rd
# A rt_fwd callback has the following prototype:
def my_rtfwd_cb(msg):
print "Forwarding the following message:"
msg.dump()
return [ 0, msg ] # return None instead of msg to stop forwarding.
fwdhdl = fd_rt_fwd_hdl( my_rtfwd_cb, RT_FWD_REQ )
# A rt_out cb has the following prototype:
def my_rtout_cb(msg, list):
print "Sending out the following message:"
msg.dump()
print "The possible candidates are:"
for c in list.enum_as("struct rtd_candidate *"):
print "%s (%s): %s" % (c.diamid, c.realm, c.score)
return 0 # returns an error code (standard errno values)
outhdl = fd_rt_out_hdl( my_rtout_cb ) # a priority can be specified as 2nd parameter, default is 0.
############# Messages, AVPs ############
...
...
@@ -321,7 +346,7 @@ vsai = avp(cvar.fd_g_config.cnf_dict.search ( DICT_AVP, AVP_BY_NAME, "Vendor-Spe
# Set values
val = avp_value()
val.u32 = 123
vi.setval(None) # this cleans a previous value (not needed)
vi.setval(None) # this cleans a previous value (
usually
not needed)
vi.setval(val)
val.os = "my.origin.host"
oh.setval(val)
...
...
@@ -378,7 +403,7 @@ avp = avp.get_next() # when last AVP, returns None
# Get all 1st level children (slower) -- warning, changes to the python list will not be reflected on the underlying message. read-only use.
dwr.children()
# example use:
for a in dwr.children()
for a in dwr.children()
:
a.dump(0) # 0 means: dump only this object, do not walk the tree
...
...
@@ -435,6 +460,7 @@ gavp.children()
# Send a message:
mydwr = msg(buf)
mydwr.send()
# Optionaly, a callback can be registered when a message is sent, with an optional object.
...
...
@@ -446,10 +472,12 @@ def send_callback(msg, obj):
obj
return None
mydwr = msg(buf)
mydwr.send(send_callback, some_object)
# Set a result code in an answer message.
mydwr = msg(buf)
dwa = mydwr.create_answer()
dwa.rescode_set() # This adds the DIAMETER_SUCCESS result code
dwa.rescode_set("DIAMETER_LIMITED_SUCCESS" ) # This adds a different result code
...
...
@@ -597,6 +625,21 @@ myqueue.timedget(3)
# Show the number of items in the queue
myqueue.length()
## Variants:
# All the previous calls are suitable to queue Python objects.
# In order to interact with objects queued / poped by C counterpart,
# a second parameter must be passed to specify the object type,
# as follow:
ev = fd_event()
ev.code = FDEV_DUMP_EXT
cvar.fd_g_config.cnf_main_ev.post(ev, "struct fd_event *")
# Similarly, for *get, we can specify the structure that was queued:
myqueue.get("struct fd_event *")
myqueue.tryget("struct fd_event *")
myqueue.timedget(3, "struct fd_event *")
del myqueue
...
...
@@ -613,9 +656,7 @@ for p in peers:
# Create a new peer
np = peer_info()
np.pi_diamid = "nas.localdomain"
np.config.pic_flags.pro4 = 1 # 1 for TCP, for some reason PI_P4_TCP is not defined
np.config.pic_flags.pro4 = PI_P4_TCP
# Add this peer into the framework.
...
...
@@ -633,7 +674,55 @@ def add_cb(peer):
else:
print "The peer has been destroyed before it completed the connection."
# Then add the peer
simply
like this:
# Then add the peer like this:
np.add(add_cb)
# Search a peer by its diameter id (returns a peer_hdr object if found) -- similar to fd_peer_getbyid
p = peer_search("nas.domain.aaa")
## Validation callback (see fd_peer_validate_register documentation)
# cb2 prototype:
def my_validate_cb2(pinfo):
print "Cb2 callback trigged for peer %s" % (pinfo.pi_diamid)
# Usually, this would be used only to check some TLS properties,
# which is not really possible yet through the python interpreter...
return 0 # return an error code if the peer is not validated
# cb prototype:
def my_validate_cb(pinfo):
print "Validate callback trigged for peer %s" % (pinfo.pi_diamid)
# If the peer is not allowed to connect:
#return -1
# If the peer is authorized:
#return 1
# In addition, if IPsec is allowed,
#pinfo.config.pic_flags.sec = PI_SEC_NONE
# If no decision has been made:
#return 0
# If the peer is temporarily authorized but a second callback must be called after TLS negociation:
return my_validate_cb2
# Register the callback, it will be called on new incoming connections.
peer_validate_register(my_validate_cb)
############# ENDPOINTS ############
ep = fd_endpoint("129.168.168.192")
# with port:
ep = fd_endpoint("129.168.168.192", 3868)
# With different flags:
ep = fd_endpoint("129.168.168.192", 3868, EP_FL_PRIMARY)
# Add IP information for the peer
np = peer_info()
ep.add_merge(np.pi_endpoints)
fd_ep_dump(0, np.pi_endpoints)
extensions/dbg_interactive/CMakeLists.txt
View file @
0c11a767
...
...
@@ -25,6 +25,8 @@ SET(SWIG_MODULE_fDpy_EXTRA_DEPS
dispatch.i
queues.i
peers.i
events.i
endpoints.i
)
SET_SOURCE_FILES_PROPERTIES
(
dbg_interactive.i PROPERTIES SWIG_MODULE_NAME fDpy
)
...
...
extensions/dbg_interactive/dbg_interactive.i
View file @
0c11a767
...
...
@@ -67,7 +67,7 @@
/* This is not thread-safe etc. but it should work /most of the time/. */
static
int
wrapper_errno
;
static
PyObject
*
wrapper_errno_py
;
static
char
*
wrapper_error_txt
;
/* if NULL, use strerror(errno) */
static
const
char
*
wrapper_error_txt
;
/* if NULL, use strerror(errno) */
#
define
DI_ERROR
(
code
,
pycode
,
str
)
{
\
fd_log_debug
(
"[dbg_interactive] ERROR: %s: %s
\n
"
,
__PRETTY_FUNCTION__
,
str
?
str
:
strerror
(
code
))
;
\
wrapper_errno
=
code
;
\
...
...
@@ -87,7 +87,7 @@ static char * wrapper_error_txt; /* if NULL, use strerror(errno) */
$
action
/* Now, test for error */
if
(
wrapper_errno
)
{
char
*
str
=
wrapper_error_txt
?
wrapper_error_txt
:
strerror
(
wrapper_errno
)
;
const
char
*
str
=
wrapper_error_txt
?
wrapper_error_txt
:
strerror
(
wrapper_errno
)
;
PyObject
*
exc
=
wrapper_errno_py
;
if
(
!
exc
)
{
switch
(
wrapper_errno
)
{
...
...
@@ -108,7 +108,7 @@ static char * wrapper_error_txt; /* if NULL, use strerror(errno) */
Some types & typemaps for usability
***********************************/
%
apply
(
char
*
STRING
,
size_t
LENGTH
)
{
(
char
*
string
,
size_t
len
)
}
;
/* fd_hash */
%
apply
(
char
*
STRING
,
size_t
LENGTH
)
{
(
char
*
string
,
size_t
len
)
}
;
/* Generic typemap for functions that create something */
%
typemap
(
in
,
numinputs
=
0
,
noblock
=
1
)
SWIGTYPE
**
OUTPUT
(
void
*
temp
=
NULL
)
{
...
...
@@ -118,21 +118,42 @@ static char * wrapper_error_txt; /* if NULL, use strerror(errno) */
%
append_output
(
SWIG_NewPointerObj
(
*
$
1
,
$
*
1
_descriptor
,
0
))
;
}
/* Typemap to return a boolean value as output parameter */
%
typemap
(
in
,
numinputs
=
0
,
noblock
=
1
)
int
*
BOOL_OUT
(
int
temp
)
{
$
1
=
&
temp;
}
%
typemap
(
argout
,
noblock
=
1
)
int
*
BOOL_OUT
{
PyObject
*
r
;
if
(
*
$
1
)
r
=
Py_True
;
else
r
=
Py_False
;
Py_XINCREF
(
r
)
;
%
append_output
(
r
)
;
}
/* To allow passing callback functions defined in python */
%
typemap
(
in
)
PyObject
*
PyCb
{
if
(
!
PyCallable_Check
(
$
input
))
{
PyErr_SetString
(
PyExc_TypeError
,
"Need a callable object!"
)
;
SWIG_fail
;
if
(
!
$
input
||
(
$
input
==
Py_None
))
{
$
1
=
NULL
;
}
else
{
if
(
!
PyCallable_Check
(
$
input
))
{
PyErr_SetString
(
PyExc_TypeError
,
"Need a callable object!"
)
;
SWIG_fail
;
}
$
1
=
$
input
;
}
$
1
=
$
input
;
}
/* Forward declaration for the peers module */
%
{
/* Forward declaration for the peers module */
static
void
fd_add_cb
(
struct
peer_info
*
peer
,
void
*
data
)
;
%
}
/* Overwrite declaration to apply typemaps */
int
fd_sess_fromsid
(
char
*
STRING
,
size_t
LENGTH
,
struct
session
**
OUTPUT
,
int
*
BOOL_OUT
)
;
/*********************************************************
Now, create wrappers for (almost) all objects from fD API
*********************************************************/
...
...
@@ -154,3 +175,5 @@ for more usable python-style versions.
%
include
"queues.i"
%
include
"peers.i"
%
include
"events.i"
%
include
"endpoints.i"
extensions/dbg_interactive/endpoints.i
0 → 100644
View file @
0c11a767
/*********************************************************************************************************
* Software License Agreement (BSD License) *
* Author: Sebastien Decugis <sdecugis@nict.go.jp> *
* *
* Copyright (c) 2010, WIDE Project and NICT *
* All rights reserved. *
* *
* Redistribution and use of this software in source and binary forms, with or without modification, are *
* permitted provided that the following conditions are met: *
* *
* * Redistributions of source code must retain the above *
* copyright notice, this list of conditions and the *
* following disclaimer. *
* *
* * Redistributions in binary form must reproduce the above *
* copyright notice, this list of conditions and the *
* following disclaimer in the documentation and/or other *
* materials provided with the distribution. *
* *
* * Neither the name of the WIDE Project or NICT nor the *
* names of its contributors may be used to endorse or *
* promote products derived from this software without *
* specific prior written permission of WIDE Project and *
* NICT. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT *
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS *
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF *
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
*********************************************************************************************************/
/* Do not include this directly, use dbg_interactive.i instead */
/****** ENDPOINTS *********/
%
{
#
include
<
sys
/
socket
.
h
>
#
include
<
netdb
.
h
>
%
}
%
extend
fd_endpoint
{
fd_endpoint
()
{
struct
fd_endpoint
*
np
=
(
struct
fd_endpoint
*
)
calloc
(
1
,
sizeof
(
struct
fd_endpoint
))
;
if
(
!
np
)
{
DI_ERROR_MALLOC
;
return
NULL
;
}
fd_list_init
(
&
np->chain,
np);
return
np
;
}
fd_endpoint
(
const
char
*
endpoint
,
uint16_t
port
=
0
,
uint32_t
flags
=
EP_FL_CONF
)
{
struct
addrinfo
hints
;
struct
addrinfo
*
ai
=
NULL
;
int
ret
;
memset
(
&
hints,
0
,
sizeof(hints));
hints
.
ai_family
=
AF_UNSPEC
;
hints
.
ai_flags
=
AI_NUMERICHOST
;
ret
=
getaddrinfo
(
endpoint
,
NULL
,
&
hints,
&
ai);
if
(
ret
)
{
DI_ERROR
(
ret
,
PyExc_ValueError
,
gai_strerror
(
ret
))
;
return
NULL
;
}
if
(
port
)
{
switch
(
ai-
>
ai_family
)
{
case
AF_INET
:
((
sSA4
*
)
ai-
>
ai_addr
)
->
sin_port
=
htons
(
port
)
;
break
;
case
AF_INET6
:
((
sSA6
*
)
ai-
>
ai_addr
)
->
sin6_port
=
htons
(
port
)
;
break
;
default
:
DI_ERROR
(
EINVAL
,
PyExc_RuntimeError
,
"Unknown family returned by getaddrinfo"
)
;
return
NULL
;
}
}
struct
fd_endpoint
*
np
=
(
struct
fd_endpoint
*
)
calloc
(
1
,
sizeof
(
struct
fd_endpoint
))
;
if
(
!
np
)
{
DI_ERROR_MALLOC
;
return
NULL
;
}
fd_list_init
(
&
np->chain,
np);
memcpy
(
&
np->s.sa,
ai->ai_addr,
ai->ai_addrlen);
freeaddrinfo
(
ai
)
;
np-
>
flags
=
flags
;
return
np
;
}
~
fd_endpoint
()
{
fd_list_unlink
(
&
$self->chain);
free
(
$
self
)
;
}
/* Merge to a list */
%
delobject
add_merge
;
void
add_merge
(
struct
fd_list
*
eplist
)
{
int
ret
;
if
(
!
eplist
)
{
DI_ERROR
(
EINVAL
,
NULL
,
NULL
)
;
return
;
}
ret
=
fd_ep_add_merge
(
eplist
,
&
$self->s.sa,
sSAlen(&$self->s.sa),
$self->flags
);
if
(
ret
)
{
DI_ERROR
(
ret
,
NULL
,
NULL
)
;
return
;
}
return
;
}
void
dump
()
{
fd_ep_dump_one
(
""
,
$
self
,
"
\n
"
)
;
}
}
extensions/dbg_interactive/events.i
0 → 100644
View file @
0c11a767
/*********************************************************************************************************
* Software License Agreement (BSD License) *
* Author: Sebastien Decugis <sdecugis@nict.go.jp> *
* *
* Copyright (c) 2010, WIDE Project and NICT *
* All rights reserved. *
* *
* Redistribution and use of this software in source and binary forms, with or without modification, are *
* permitted provided that the following conditions are met: *
* *
* * Redistributions of source code must retain the above *
* copyright notice, this list of conditions and the *
* following disclaimer. *
* *
* * Redistributions in binary form must reproduce the above *
* copyright notice, this list of conditions and the *
* following disclaimer in the documentation and/or other *
* materials provided with the distribution. *
* *
* * Neither the name of the WIDE Project or NICT nor the *
* names of its contributors may be used to endorse or *
* promote products derived from this software without *
* specific prior written permission of WIDE Project and *
* NICT. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT *
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS *
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF *
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
*********************************************************************************************************/
/* Do not include this directly, use dbg_interactive.i instead */
/****** EVENTS *********/
%
extend
fd_event
{
fd_event
(
int
code
,
char
*
STRING
,
size_t
LENGTH
)
{
struct
fd_event
*
fd
=
calloc
(
1
,
sizeof
(
struct
fd_event
))
;
if
(
!
fd
)
{
DI_ERROR_MALLOC
;
return
NULL
;
}
fd-
>
code
=
code
;
fd-
>
data
=
STRING
;
/* Should maybe malloc it ? */
fd-
>
size
=
LENGTH
;
return
fd
;
}
}
extensions/dbg_interactive/lists.i
View file @
0c11a767
...
...
@@ -70,8 +70,14 @@
fd_list_insert_after
(
$
self
,
li
)
;
}
/* Test for emptyness */
int
isempty
()
{
return
FD_IS_LIST_EMPTY
(
$
self
)
;
PyObject
*
isempty
()
{
PyObject
*
ret
;
if
(
FD_IS_LIST_EMPTY
(
$
self
))
ret
=
Py_True
;
else
ret
=
Py_False
;
Py_XINCREF
(
ret
)
;
return
ret
;
}
/* Concatenate two lists */
void
concat
(
struct
fd_list
*
li
)
{
...
...
extensions/dbg_interactive/messages.i
View file @
0c11a767
...
...
@@ -292,8 +292,14 @@ struct msg {
}
/* Is routable? */
int
is_routable
()
{
return
fd_msg_is_routable
(
$
self
)
;
PyObject
*
is_routable
()
{
PyObject
*
r
;
if
(
fd_msg_is_routable
(
$
self
))
r
=
Py_True
;
else
r
=
Py_False
;
Py_XINCREF
(
r
)
;
return
r
;
}
/* Get the source */
...
...
extensions/dbg_interactive/peers.i
View file @
0c11a767
...
...
@@ -66,7 +66,20 @@ static void fd_add_cb(struct peer_info *peer, void *data) {
%
}
%
extend
peer_info
{
peer_info
()
{
struct
peer_info
*
np
=
(
struct
peer_info
*
)
calloc
(
1
,
sizeof
(
struct
peer_info
))
;
if
(
!
np
)
{
DI_ERROR_MALLOC
;
return
NULL
;
}
fd_list_init
(
&
np->pi_endpoints,
NULL);
return
np
;
}
/* Wrapper around fd_peer_add to allow calling the python callback */
%
delobject
add
;
void
add
(
PyObject
*
PyCb
=
NULL
)
{
int
ret
;
...
...
@@ -80,10 +93,135 @@ static void fd_add_cb(struct peer_info *peer, void *data) {
DI_ERROR
(
ret
,
NULL
,
NULL
)
;
}
}
}
%
inline
%
{
static
struct
peer_hdr
*
peer_search
(
char
*
diamid
)
{
struct
peer_hdr
*
r
=
NULL
;
int
ret
=
fd_peer_getbyid
(
diamid
,
&
r
);
if
(
ret
)
{
DI_ERROR
(
ret
,
NULL
,
NULL
)
;
return
NULL
;
}
return
r
;
}
%
}
/* Add an endpoint */
void
add_endpoint
(
char
*
endpoint
)
{
fd_log_debug
(
"What is the best way in python to pass an endpoint? (ip + port)"
)
;
%
{
static
PyObject
*
validate_cb_py
=
NULL
;
static
PyObject
*
validate_cb2_py
=
NULL
;
/* C wrapper that calls validate_cb2_py */
int
call_the_python_validate_callback2
(
struct
peer_info
*
info
)
{
PyObject
*
PyInfo
;
PyObject
*
result
=
NULL
;
int
ret
=
0
;
if
(
!
validate_cb2_py
)
{
fd_log_debug
(
"Internal error: missing the callback2!
\n
"
)
;
return
ENOTSUP
;
}
SWIG_PYTHON_THREAD_BEGIN_BLOCK
;
/* Convert the arguments */
PyInfo
=
SWIG_NewPointerObj
((
void
*
)
info
,
SWIGTYPE_p_peer_info
,
0
)
;
/* Call the function */
result
=
PyEval_CallFunction
(
validate_cb2_py
,
"(O)"
,
PyInfo
)
;
/* The result is an integer */
if
((
result
==
NULL
)
||
!
SWIG_IsOK
(
SWIG_AsVal_int
(
result
,
&
ret)))
{
fd_log_debug
(
"Error: The Python callback did not return an integer.
\n
"
)
;
ret
=
EINVAL
;
goto
out
;
}
out
:
Py_XDECREF
(
result
)
;
SWIG_PYTHON_THREAD_END_BLOCK
;
return
ret
;
}
/* C wrapper that calls validate_cb_py */
int
call_the_python_validate_callback
(
struct
peer_info
*
info
,
int
*
auth
,
int
(
**
cb2
)(
struct
peer_info
*
))
{
PyObject
*
PyInfo
;
PyObject
*
result
=
NULL
;
int
ret
=
0
;
if
(
!
validate_cb_py
)
{
fd_log_debug
(
"Internal error: missing the callback!
\n
"
)
;
return
ENOTSUP
;
}
SWIG_PYTHON_THREAD_BEGIN_BLOCK
;
/* Convert the arguments */
PyInfo
=
SWIG_NewPointerObj
((
void
*
)
info
,
SWIGTYPE_p_peer_info
,
0
)
;
/* Call the function */
result
=
PyEval_CallFunction
(
validate_cb_py
,
"(O)"
,
PyInfo
)
;
/* The result is supposedly -1, 1, or a cb2 */
if
(
result
==
NULL
)
{
fd_log_debug
(
"Error: The Python callback did not return a value.
\n
"
)
;
ret
=
EINVAL
;
goto
out
;
}
if
(
PyCallable_Check
(
result
))
{
if
(
cb2
)
{
if
(
validate_cb2_py
&
&
(validate_cb2_py
!=
result))
{
fd_log_debug
(
"Only 1 register callback2 is supported currently
\n
"
)
;
ret
=
ENOTSUP
;
goto
out
;
}
validate_cb2_py
=
result
;
*
cb2
=
call_the_python_validate_callback2
;
*
auth
=
1
;
goto
out_nodec
;
}
else
{
*
auth
=
1
;
goto
out
;
/* ignore the callback since it won't be used */
}
}
else
{
/* In this case, the return value must be -1, 0, or 1 */
if
(
!
SWIG_IsOK
(
SWIG_AsVal_int
(
result
,
auth
)))
{
fd_log_debug
(
"Error: Cannot convert the return value to integer.
\n
"
)
;
ret
=
EINVAL
;