reSIProcate
SIP stack, Dialog Usage Manager and related libraries
Loading...
Searching...
No Matches
PyRoutePlugin.cxx
Go to the documentation of this file.
1
2// NOTE: Python.h must be included before any standard headers
3// See: https://bugzilla.redhat.com/show_bug.cgi?id=518385
4
5/* Using the PyCXX API for C++ Python integration
6 * It is extremely convenient and avoids the need to write boilerplate
7 * code for handling the Python reference counts.
8 * It is licensed under BSD terms compatible with reSIProcate */
9#include <Python.h>
10#include <CXX/Objects.hxx>
11#include <CXX/Extensions.hxx>
12
13#include <memory>
14#include <utility>
15
16#include "rutil/Logger.hxx"
19#include "repro/Plugin.hxx"
20#include "repro/Processor.hxx"
21#include "repro/Proxy.hxx"
24
26
27#include "PyRouteWorker.hxx"
29#include "PyRouteProcessor.hxx"
30
31#define RESIPROCATE_SUBSYSTEM resip::Subsystem::REPRO
32
33using namespace resip;
34using namespace repro;
35
37{
38 public:
40 {
41 };
42
44 {
45 };
46
47 virtual bool onStartup() override
48 {
49 std::unique_ptr<Py::Module> pyModule = loadModule(mRouteScript);
50 if(!pyModule)
51 {
52 return false;
53 }
54
55 if(pyModule->getDict().hasKey("on_load"))
56 {
57 DebugLog(<< "found on_load method, trying to invoke it...");
58 try
59 {
60 StackLog(<< "invoking on_load");
61 pyModule->callMemberFunction("on_load");
62 }
63 catch (const Py::Exception& ex)
64 {
65 DebugLog(<< "call to on_load method failed: " << Py::value(ex));
66 StackLog(<< Py::trace(ex));
67 return false;
68 }
69 }
70
71 mPyModule = std::move(pyModule);
72
73 mAction = mPyModule->getAttr("provide_route");
74 if(mPyModule->getDict().hasKey("on_message"))
75 {
76 mMessageHandlerAction = mPyModule->getAttr("on_message");
77 }
78
79 return true;
80 }
81
82
83 virtual bool init(SipStack& sipStack, ProxyConfig *proxyConfig) override
84 {
85 DebugLog(<<"PyRoutePlugin: init called");
86
87 if(!proxyConfig)
88 {
89 ErrLog(<<"proxyConfig == 0, aborting");
90 return false;
91 }
92
93 Data pyPath(proxyConfig->getConfigData("PyRoutePath", "", true));
94 mRouteScript = proxyConfig->getConfigData("PyRouteScript", "", true);
95 if(pyPath.empty())
96 {
97 ErrLog(<<"PyRoutePath not specified in config, aborting");
98 return false;
99 }
100 if(mRouteScript.empty())
101 {
102 ErrLog(<<"PyRouteScript not specified in config, aborting");
103 return false;
104 }
105
106 if(!PyExtensionBase::init(pyPath))
107 {
108 return false;
109 }
110
111 int numPyRouteWorkerThreads = proxyConfig->getConfigInt("PyRouteNumWorkerThreads", 2);
112 std::unique_ptr<Worker> worker(new PyRouteWorker(*this, mAction, mMessageHandlerAction));
113 mDispatcher.reset(new Dispatcher(std::move(worker), &sipStack, numPyRouteWorkerThreads));
114
115 mMessageHandler.reset(new PyRouteMessageHandler(*mDispatcher));
116 sipStack.addTransportSipMessageLoggingHandler(mMessageHandler);
117
118 return true;
119 }
120
122 {
123 DebugLog(<<"PyRoutePlugin: onRequestProcessorChainPopulated called");
124
125 // The module class is also the monkey class, no need to create
126 // any monkey instance here
127
128 // Add the pyroute monkey to the chain ahead of LocationServer
129 std::unique_ptr<Processor> proc(new PyRouteProcessor(*mDispatcher));
130 chain.insertProcessor<LocationServer>(std::move(proc));
131 }
132
134 {
135 DebugLog(<<"PyRoutePlugin: onResponseProcessorChainPopulated called");
136 }
137
139 {
140 DebugLog(<<"PyRoutePlugin: onTargetProcessorChainPopulated called");
141 }
142
143 virtual void onReload() override
144 {
145 DebugLog(<<"PyRoutePlugin: onReload called");
146 }
147
148 private:
149 Data mRouteScript;
150 std::unique_ptr<Py::Module> mPyModule;
151 Py::Callable mAction;
152 Py::Callable mMessageHandlerAction;
153 std::unique_ptr<Dispatcher> mDispatcher;
154 std::shared_ptr<PyRouteMessageHandler> mMessageHandler;
155};
156
157
158extern "C" {
159
160static
161std::shared_ptr<resip::Plugin> instantiate()
162{
163 return std::make_shared<PyRoutePlugin>();
164}
165
171
172};
173
174/* ====================================================================
175 *
176 * Copyright (c) 2022, Software Freedom Institute https://softwarefreedom.institute
177 * Copyright (c) 2013-2022, Daniel Pocock https://danielpocock.com
178 *
179 * Redistribution and use in source and binary forms, with or without
180 * modification, are permitted provided that the following conditions
181 * are met:
182 *
183 * 1. Redistributions of source code must retain the above copyright
184 * notice, this list of conditions and the following disclaimer.
185 *
186 * 2. Redistributions in binary form must reproduce the above copyright
187 * notice, this list of conditions and the following disclaimer in
188 * the documentation and/or other materials provided with the
189 * distribution.
190 *
191 * 3. Neither the name of the author(s) nor the names of any contributors
192 * may be used to endorse or promote products derived from this software
193 * without specific prior written permission.
194 *
195 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS "AS IS" AND
196 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
197 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
198 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE
199 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
200 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
201 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
202 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
203 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
204 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
205 * SUCH DAMAGE.
206 *
207 * ====================================================================
208 *
209 *
210 */
211
#define DebugLog(args_)
Definition Logger.hxx:128
#define StackLog(args_)
Definition Logger.hxx:125
#define ErrLog(args_)
Definition Logger.hxx:137
PluginDescriptor reproPluginDesc
static std::shared_ptr< resip::Plugin > instantiate()
virtual bool init(SipStack &sipStack, ProxyConfig *proxyConfig) override
virtual ~PyRoutePlugin()
virtual void onTargetProcessorChainPopulated(ProcessorChain &chain) override
virtual void onResponseProcessorChainPopulated(ProcessorChain &chain) override
virtual void onRequestProcessorChainPopulated(ProcessorChain &chain) override
virtual void onReload() override
virtual bool onStartup() override
void insertProcessor(std::unique_ptr< Processor > rp)
int getConfigInt(const resip::Data &name, int defaultValue) const
resip::Data getConfigData(const resip::Data &name, const resip::Data &defaultValue, bool useDefaultIfEmpty=false) const
An alternative to std::string, encapsulates an arbitrary buffer of bytes.
Definition Data.hxx:90
bool empty() const noexcept
Checks whether the Data is empty.
Definition Data.hxx:591
A generic thread-bank class.
virtual std::unique_ptr< Py::Module > loadModule(const resip::Data &moduleName)
virtual bool init(const resip::Data &pyPath)
This is the primary point of interaction between the app-layer and the stack.
Definition SipStack.hxx:160
void addTransportSipMessageLoggingHandler(std::shared_ptr< Transport::SipMessageLoggingHandler > handler)
Used by the application to provide a handler that will get called for all inbound and outbound SIP me...
Definition SipStack.cxx:343
This Class is used to implement a primitive form of RPC using loose XML formatting.
dcm! – add UnusedChecking(_enum) below;
#define REPRO_DSO_PLUGIN_API_VERSION
Definition Plugin.hxx:38