#include "ns3module.h"
#include "ns3/ref-count-base.h"
#include <unistd.h>
#if PY_VERSION_HEX >= 0x03000000
# define PyInt_AsUnsignedLongMask PyLong_AsUnsignedLongMask
# define PyString_FromStringAndSize PyUnicode_FromStringAndSize
#endif
namespace {
class PythonEventImpl : public ns3::EventImpl
{
private:
PyObject *m_callback;
PyObject *m_args;
public:
PythonEventImpl (PyObject *callback, PyObject *args, PyObject *py_context=NULL)
{
m_callback = callback;
Py_INCREF (m_callback);
if (py_context == NULL)
{
m_args = args;
Py_INCREF (m_args);
}
else
{
Py_ssize_t arglen = PyTuple_GET_SIZE (args);
m_args = PyTuple_New (arglen + 1);
PyTuple_SET_ITEM (m_args, 0, py_context);
Py_INCREF (py_context);
for (Py_ssize_t i = 0; i < arglen; ++i)
{
PyObject *arg = PyTuple_GET_ITEM (args, i);
Py_INCREF (arg);
PyTuple_SET_ITEM (m_args, 1 + i, arg);
}
}
}
virtual ~PythonEventImpl ()
{
PyGILState_STATE __py_gil_state = PyGILState_Ensure ();
Py_DECREF (m_callback);
Py_DECREF (m_args);
PyGILState_Release (__py_gil_state);
}
virtual void Notify ()
{
PyGILState_STATE __py_gil_state = PyGILState_Ensure ();
PyObject *retval = PyObject_CallObject (m_callback, m_args);
if (retval) {
if (retval != Py_None) {
PyErr_SetString (PyExc_TypeError, "event callback should return None");
PyErr_Print ();
}
Py_DECREF (retval);
} else {
PyErr_Print ();
}
PyGILState_Release (__py_gil_state);
}
};
} // closes: namespace {
PyObject *
_wrap_Simulator_Schedule (PyNs3Simulator *PYBINDGEN_UNUSED (dummy), PyObject *args, PyObject *kwargs,
PyObject **return_exception)
{
PyObject *exc_type, *traceback;
PyObject *py_time;
PyObject *py_callback;
PyObject *user_args;
ns3::Ptr<PythonEventImpl> py_event_impl;
PyNs3EventId *py_EventId;
if (kwargs && PyObject_Length (kwargs) > 0) {
PyErr_SetString (PyExc_TypeError, "keyword arguments not supported");
goto error;
}
if (PyTuple_GET_SIZE (args) < 2) {
PyErr_SetString (PyExc_TypeError, "ns3.Simulator.Schedule needs at least 2 arguments");
goto error;
}
py_time = PyTuple_GET_ITEM (args, 0);
py_callback = PyTuple_GET_ITEM (args, 1);
if (!PyObject_IsInstance (py_time, (PyObject*) &PyNs3Time_Type)) {
PyErr_SetString (PyExc_TypeError, "Parameter 1 should be a ns3.Time instance");
goto error;
}
if (!PyCallable_Check (py_callback)) {
PyErr_SetString (PyExc_TypeError, "Parameter 2 should be callable");
goto error;
}
user_args = PyTuple_GetSlice (args, 2, PyTuple_GET_SIZE (args));
py_event_impl = ns3::Create<PythonEventImpl>(py_callback, user_args);
Py_DECREF (user_args);
py_EventId = PyObject_New (PyNs3EventId, &PyNs3EventId_Type);
py_EventId->obj = new ns3::EventId (
ns3::Simulator::Schedule (*((PyNs3Time *) py_time)->obj, py_event_impl));
py_EventId->flags = PYBINDGEN_WRAPPER_FLAG_NONE;
return (PyObject *) py_EventId;
error:
PyErr_Fetch (&exc_type, return_exception, &traceback);
Py_XDECREF (exc_type);
Py_XDECREF (traceback);
return NULL;
}
PyObject *
_wrap_Simulator_ScheduleNow (PyNs3Simulator *PYBINDGEN_UNUSED (dummy), PyObject *args, PyObject *kwargs,
PyObject **return_exception)
{
PyObject *exc_type, *traceback;
PyObject *py_callback;
PyObject *user_args;
ns3::Ptr<PythonEventImpl> py_event_impl;
PyNs3EventId *py_EventId;
if (kwargs && PyObject_Length (kwargs) > 0) {
PyErr_SetString (PyExc_TypeError, "keyword arguments not supported");
goto error;
}
if (PyTuple_GET_SIZE (args) < 1) {
PyErr_SetString (PyExc_TypeError, "ns3.Simulator.Schedule needs at least 1 argument");
goto error;
}
py_callback = PyTuple_GET_ITEM (args, 0);
if (!PyCallable_Check (py_callback)) {
PyErr_SetString (PyExc_TypeError, "Parameter 1 should be callable");
goto error;
}
user_args = PyTuple_GetSlice (args, 1, PyTuple_GET_SIZE (args));
py_event_impl = ns3::Create<PythonEventImpl>(py_callback, user_args);
Py_DECREF (user_args);
py_EventId = PyObject_New (PyNs3EventId, &PyNs3EventId_Type);
py_EventId->obj = new ns3::EventId (ns3::Simulator::ScheduleNow (py_event_impl));
py_EventId->flags = PYBINDGEN_WRAPPER_FLAG_NONE;
return (PyObject *) py_EventId;
error:
PyErr_Fetch (&exc_type, return_exception, &traceback);
Py_XDECREF (exc_type);
Py_XDECREF (traceback);
return NULL;
}
PyObject *
_wrap_Simulator_ScheduleWithContext (PyNs3Simulator *PYBINDGEN_UNUSED(dummy), PyObject *args, PyObject *kwargs,
PyObject **return_exception)
{
PyObject *exc_type, *traceback;
PyObject *py_obj_context;
uint32_t context;
PyObject *py_time;
PyObject *py_callback;
PyObject *user_args;
PythonEventImpl *py_event_impl;
if (kwargs && PyObject_Length(kwargs) > 0) {
PyErr_SetString(PyExc_TypeError, "keyword arguments not supported");
goto error;
}
if (PyTuple_GET_SIZE(args) < 3 ) {
PyErr_SetString(PyExc_TypeError, "ns3.Simulator.ScheduleWithContext needs at least 3 arguments");
goto error;
}
py_obj_context = PyTuple_GET_ITEM(args, 0);
py_time = PyTuple_GET_ITEM(args, 1);
py_callback = PyTuple_GET_ITEM(args, 2);
context = PyInt_AsUnsignedLongMask(py_obj_context);
if (PyErr_Occurred()) {
goto error;
}
if (!PyObject_IsInstance(py_time, (PyObject*) &PyNs3Time_Type)) {
PyErr_SetString(PyExc_TypeError, "Parameter 2 should be a ns3.Time instance");
goto error;
}
if (!PyCallable_Check(py_callback)) {
PyErr_SetString(PyExc_TypeError, "Parameter 3 should be callable");
goto error;
}
user_args = PyTuple_GetSlice(args, 3, PyTuple_GET_SIZE(args));
py_event_impl = new PythonEventImpl (py_callback, user_args, py_obj_context);
Py_DECREF(user_args);
ns3::Simulator::ScheduleWithContext(context, *((PyNs3Time *) py_time)->obj, py_event_impl);
Py_INCREF(Py_None);
return Py_None;
error:
PyErr_Fetch(&exc_type, return_exception, &traceback);
Py_XDECREF(exc_type);
Py_XDECREF(traceback);
return NULL;
}
PyObject *
_wrap_Simulator_ScheduleDestroy (PyNs3Simulator *PYBINDGEN_UNUSED (dummy), PyObject *args, PyObject *kwargs,
PyObject **return_exception)
{
PyObject *exc_type, *traceback;
PyObject *py_callback;
PyObject *user_args;
ns3::Ptr<PythonEventImpl> py_event_impl;
PyNs3EventId *py_EventId;
if (kwargs && PyObject_Length (kwargs) > 0) {
PyErr_SetString (PyExc_TypeError, "keyword arguments not supported");
goto error;
}
if (PyTuple_GET_SIZE (args) < 1) {
PyErr_SetString (PyExc_TypeError, "ns3.Simulator.Schedule needs at least 1 argument");
goto error;
}
py_callback = PyTuple_GET_ITEM (args, 0);
if (!PyCallable_Check (py_callback)) {
PyErr_SetString (PyExc_TypeError, "Parameter 2 should be callable");
goto error;
}
user_args = PyTuple_GetSlice (args, 1, PyTuple_GET_SIZE (args));
py_event_impl = ns3::Create<PythonEventImpl>(py_callback, user_args);
Py_DECREF (user_args);
py_EventId = PyObject_New (PyNs3EventId, &PyNs3EventId_Type);
py_EventId->obj = new ns3::EventId (ns3::Simulator::ScheduleDestroy (py_event_impl));
py_EventId->flags = PYBINDGEN_WRAPPER_FLAG_NONE;
return (PyObject *) py_EventId;
error:
PyErr_Fetch (&exc_type, return_exception, &traceback);
Py_XDECREF (exc_type);
Py_XDECREF (traceback);
return NULL;
}
PyObject *
_wrap_TypeId_LookupByNameFailSafe (PyNs3TypeId *PYBINDGEN_UNUSED (dummy), PyObject *args, PyObject *kwargs,
PyObject **return_exception)
{
bool ok;
const char *name;
Py_ssize_t name_len;
ns3::TypeId tid;
PyNs3TypeId *py_tid;
const char *keywords[] = { "name", NULL};
if (!PyArg_ParseTupleAndKeywords (args, kwargs, (char *) "s#", (char **) keywords, &name, &name_len)) {
PyObject *exc_type, *traceback;
PyErr_Fetch (&exc_type, return_exception, &traceback);
Py_XDECREF (exc_type);
Py_XDECREF (traceback);
return NULL;
}
ok = ns3::TypeId::LookupByNameFailSafe (std::string (name, name_len), &tid);
if (!ok)
{
PyErr_Format (PyExc_KeyError, "The ns3 type with name `%s' is not registered", name);
return NULL;
}
py_tid = PyObject_New (PyNs3TypeId, &PyNs3TypeId_Type);
py_tid->obj = new ns3::TypeId (tid);
PyNs3TypeId_wrapper_registry[(void *) py_tid->obj] = (PyObject *) py_tid;
return (PyObject *) py_tid;
}
class CommandLinePythonValueSetter : public ns3::RefCountBase
{
PyObject *m_namespace;
std::string m_variable;
public:
CommandLinePythonValueSetter (PyObject *ns, std::string const &variable) {
Py_INCREF (ns);
m_namespace = ns;
m_variable = variable;
}
bool Parse (std::string value) {
PyObject *pyvalue = PyString_FromStringAndSize (value.data (), value.size ());
PyObject_SetAttrString (m_namespace, (char *) m_variable.c_str (), pyvalue);
if (PyErr_Occurred ()) {
PyErr_Print ();
return false;
}
return true;
}
virtual ~CommandLinePythonValueSetter () {
Py_DECREF (m_namespace);
m_namespace = NULL;
}
};
PyObject *
_wrap_CommandLine_AddValue (PyNs3CommandLine *self, PyObject *args, PyObject *kwargs,
PyObject **return_exception)
{
const char *name, *help, *variable = NULL;
PyObject *py_namespace = NULL;
const char *keywords[] = { "name", "help", "variable", "namespace", NULL};
if (!PyArg_ParseTupleAndKeywords (args, kwargs, (char *) "ss|sO", (char **) keywords, &name, &help, &variable, &py_namespace)) {
PyObject *exc_type, *traceback;
PyErr_Fetch (&exc_type, return_exception, &traceback);
Py_XDECREF (exc_type);
Py_XDECREF (traceback);
return NULL;
}
if (variable == NULL) {
variable = name;
}
if (py_namespace == NULL) {
py_namespace = (PyObject *) self;
}
ns3::Ptr<CommandLinePythonValueSetter> setter = ns3::Create<CommandLinePythonValueSetter> (py_namespace, variable);
self->obj->AddValue (name, help, ns3::MakeCallback (&CommandLinePythonValueSetter::Parse, setter));
Py_INCREF (Py_None);
return Py_None;
}
class PythonSimulator
{
public:
PythonSimulator();
void Run(void);
bool IsFailed(void) const;
private:
void DoCheckSignals(void);
void DoRun(void);
volatile bool m_stopped;
bool m_failed;
volatile bool m_isCheckPending;
ns3::Ptr<ns3::SystemThread> m_thread;
PyThreadState *m_py_thread_state;
};
PythonSimulator::PythonSimulator()
: m_stopped(false),
m_failed(false),
m_isCheckPending(false)
{
m_thread = ns3::Create<ns3::SystemThread>(ns3::MakeCallback(&PythonSimulator::DoRun, this));
m_py_thread_state = NULL;
}
void
PythonSimulator::Run(void)
{
m_failed = false;
m_stopped = false;
m_isCheckPending = false;
m_thread->Start();
Py_BEGIN_ALLOW_THREADS;
ns3::Simulator::Run ();
Py_END_ALLOW_THREADS;
m_stopped = true;
m_thread->Join();
}
bool
PythonSimulator::IsFailed(void) const
{
return m_failed;
}
void
PythonSimulator::DoCheckSignals(void)
{
PyGILState_STATE __py_gil_state = PyGILState_Ensure ();
PyErr_CheckSignals ();
if (PyErr_Occurred ())
{
m_failed = true;
ns3::Simulator::Stop();
}
PyGILState_Release (__py_gil_state);
m_isCheckPending = false;
}
void
PythonSimulator::DoRun(void)
{
while (!m_stopped)
{
if (!m_isCheckPending)
{
m_isCheckPending = true;
ns3::Simulator::ScheduleWithContext(0xffffffff, ns3::Seconds(0.0),
&PythonSimulator::DoCheckSignals, this);
}
usleep(200000);
}
}
PyObject *
_wrap_Simulator_Run (PyNs3Simulator *PYBINDGEN_UNUSED (dummy), PyObject *args, PyObject *kwargs,
PyObject **return_exception)
{
PythonSimulator simulator;
simulator.Run();
if (simulator.IsFailed())
{
return NULL;
}
Py_INCREF (Py_None);
return Py_None;
}