• Main Page
  • Classes
  • Files
  • File List
  • File Members

Beesnest/Engines/BnPython/BnPython.cpp

Go to the documentation of this file.
00001 
00002 #include "BnPython.h"
00003 
00004 /* This is the print function to set stuff to the server. */
00005 static PyObject* Print (PyObject *self, PyObject *args)
00006 {
00007     BnPython* myObj = BnPython::GetPointer (PyInt_AsLong (self));
00008     if (!myObj) return NULL;
00009     /* all args are the stuff to print */
00010     PyObject *itr = PyObject_GetIter(args);
00011     if (itr == NULL) return NULL;
00012     PyObject *item, *str;
00013     const char* ps;
00014     while (item = PyIter_Next(itr))
00015     {
00016         if (str = PyObject_Str (item))
00017             if (ps = PyString_AsString (str))
00018                 myObj->sBuffer += ps;
00019         Py_DECREF(str);
00020         Py_DECREF(item);
00021     }
00022     Py_DECREF(itr);
00023     if (!myObj->CheckSizeLimit ())
00024         return NULL;
00025     Py_RETURN_NONE;
00026 }
00027 
00028 /*
00029  * The following functions are wrappers for the IdcRequest, IdcResponse and
00030  * IdcAdaptersSet objects. most of it is pretty much the same in every function.
00031  */
00032 static PyObject* GetRequestHeader (PyObject *self, PyObject *args)
00033 {
00034     BnPython* myObj = BnPython::GetPointer (PyInt_AsLong (self));
00035     if (!myObj) return NULL;
00036     const char* name;
00037     if (!PyArg_ParseTuple(args, "s", &name))
00038         return NULL;
00039     BufferHolder result = myObj->pReq->GetRequestHeader (BufferHolder (name));
00040     return Py_BuildValue("s", result.pointer);
00041 }
00042 
00043 static PyObject* GetRequestVariable (PyObject *self, PyObject *args)
00044 {
00045     BnPython* myObj = BnPython::GetPointer (PyInt_AsLong (self));
00046     if (!myObj) return NULL;
00047     const char* name;
00048     if (!PyArg_ParseTuple(args, "s", &name))
00049         return NULL;
00050     BufferHolder result = myObj->pReq->GetRequestVariable (BufferHolder (name));
00051     return Py_BuildValue("s", result.pointer);
00052 }
00053 
00054 static PyObject* SetRequestVariable (PyObject *self, PyObject *args)
00055 {
00056     BnPython* myObj = BnPython::GetPointer (PyInt_AsLong (self));
00057     if (!myObj) return NULL;
00058     const char* name;
00059     const char* value;
00060     if (!PyArg_ParseTuple(args, "ss", &name, &value))
00061         return NULL;
00062     myObj->pReq->SetRequestVariable (BufferHolder (name), BufferHolder (value));
00063     Py_RETURN_NONE;
00064 }
00065 
00066 static PyObject* GetRequestVarsNamesList (PyObject *self, PyObject *args)
00067 {
00068     BnPython* myObj = BnPython::GetPointer (PyInt_AsLong (self));
00069     if (!myObj) return NULL;
00070     const char* sep;
00071     if (!PyArg_ParseTuple(args, "s", &sep))
00072         return NULL;
00073     BufferHolder result = myObj->pReq->GetRequestVarsNamesList (BufferHolder (sep));
00074     return Py_BuildValue("s", result.pointer);
00075 }
00076 
00077 static PyObject* SetResponseHeader (PyObject *self, PyObject *args)
00078 {
00079     BnPython* myObj = BnPython::GetPointer (PyInt_AsLong (self));
00080     if (!myObj) return NULL;
00081     const char* name;
00082     const char* value;
00083     if (!PyArg_ParseTuple(args, "ss", &name, &value))
00084         return NULL;
00085     myObj->pRes->SetResponseHeader (BufferHolder (name), BufferHolder (value));
00086     Py_RETURN_NONE;
00087 }
00088 
00089 static PyObject* SetResponseCookie (PyObject *self, PyObject *args)
00090 {
00091     BnPython* myObj = BnPython::GetPointer (PyInt_AsLong (self));
00092     if (!myObj) return NULL;
00093     const char* name;
00094     const char* value;
00095     int days = 1;
00096     const char* path = NULL;
00097     if (!PyArg_ParseTuple(args, "ss|is", &name, &value, &days, &path))
00098         return NULL;
00099     if (path)
00100         myObj->pRes->SetResponseCookie (BufferHolder (name), BufferHolder (value),
00101             days, BufferHolder (path));
00102     else
00103         myObj->pRes->SetResponseCookie (BufferHolder (name), BufferHolder (value), days);
00104     Py_RETURN_NONE;
00105 }
00106 
00107 static PyObject* Clear (PyObject *self, PyObject *args)
00108 {
00109     BnPython* myObj = BnPython::GetPointer (PyInt_AsLong (self));
00110     if (!myObj) return NULL;
00111     myObj->pRes->Clear ();
00112     myObj->sBuffer.clear ();
00113     Py_RETURN_NONE;
00114 }
00115 
00116 static PyObject* Flush (PyObject *self, PyObject *args)
00117 {
00118     BnPython* myObj = BnPython::GetPointer (PyInt_AsLong (self));
00119     if (!myObj) return NULL;
00120     try
00121     {   /* Flush my throw an exception. */
00122         myObj->pRes->Flush (BufferHolder (myObj->sBuffer.c_str (),
00123             myObj->sBuffer. size ()));
00124     }
00125     catch (int e)
00126     {   /* Beesnest socket has an exception, need to terminate the script and
00127             throw it back. */
00128         myObj->nException = e;  /* Store the exception for later. */
00129         PyErr_SetString(PyExc_SystemError, "Connection closed");
00130         return NULL;
00131     }
00132     myObj->sBuffer.clear ();
00133     Py_RETURN_NONE;
00134 }
00135 
00136 static PyObject* GetAdapter (PyObject *self, PyObject *args)
00137 {
00138     BnPython* myObj = BnPython::GetPointer (PyInt_AsLong (self));
00139     if (!myObj) return NULL;
00140     const char* name;
00141     if (!PyArg_ParseTuple(args, "s", &name))
00142         return NULL;
00143     unsigned int aid = 0;
00144     if (myObj->pSet)
00145         aid = myObj->pSet->GetAdapter (BufferHolder (name));
00146     if (aid > 0)
00147         myObj->oAdaptersList.insert (aid);
00148     return Py_BuildValue("i", aid);
00149 }
00150 
00151 static PyObject* ReleaseAdapter (PyObject *self, PyObject *args)
00152 {
00153     BnPython* myObj = BnPython::GetPointer (PyInt_AsLong (self));
00154     if (!myObj) return NULL;
00155     unsigned int aid;
00156     if (!PyArg_ParseTuple(args, "i", &aid))
00157         return NULL;
00158     if (myObj->pSet)
00159     {
00160         myObj->pSet->ReleaseAdapter (aid);
00161         myObj->oAdaptersList.erase (aid);
00162     }
00163     Py_RETURN_NONE;
00164 }
00165 
00166 static PyObject* Read (PyObject *self, PyObject *args)
00167 {
00168     BnPython* myObj = BnPython::GetPointer (PyInt_AsLong (self));
00169     if (!myObj) return NULL;
00170     unsigned int aid;
00171     const char* address;
00172     if (!PyArg_ParseTuple(args, "is", &aid, &address))
00173         return NULL;
00174     BufferHolder result ("");
00175     try
00176     {
00177         if (myObj->pSet)
00178             result = myObj->pSet->Read (aid, BufferHolder (address));
00179     }
00180     catch (BufferHolder e)
00181     {   /* e.pointer doesn't have to end with NULL */
00182         char tmp [100] = {0};
00183         strncpy (tmp, e.pointer, e.size < 100 ? e.size : 99);
00184         PyErr_SetString(PyExc_SystemError, tmp);
00185         return NULL;
00186     }
00187     return Py_BuildValue("s", result.pointer);
00188 }
00189 
00190 static PyObject* Write (PyObject *self, PyObject *args)
00191 {
00192     BnPython* myObj = BnPython::GetPointer (PyInt_AsLong (self));
00193     if (!myObj) return NULL;
00194     unsigned int aid;
00195     const char* address;
00196     const char* value = NULL;
00197     if (!PyArg_ParseTuple(args, "is|s", &aid, &address, &value))
00198         return NULL;
00199     bool result = false;
00200     try
00201     {
00202         if (myObj->pSet)
00203             result = myObj->pSet->Write (aid, BufferHolder (address),
00204                 BufferHolder (value));
00205     }
00206     catch (BufferHolder e)
00207     {   /* e.pointer doesn't have to end with NULL */
00208         char tmp [100] = {0};
00209         strncpy (tmp, e.pointer, e.size < 100 ? e.size : 99);
00210         PyErr_SetString(PyExc_SystemError, tmp);
00211         return NULL;
00212     }
00213     return Py_BuildValue("b", result);
00214 }
00215 
00216 static PyObject* Exit (PyObject *self, PyObject *args)
00217 {
00218     BnPython* myObj = BnPython::GetPointer (PyInt_AsLong (self));
00219     if (!myObj) return NULL;
00220     myObj->bExit = true;    /* Just set the exit flag to True. */
00221     return NULL;            /* NULL will terminate the script. */
00222 }
00223 
00224 /* This is the map of functions the interpreter will get */
00225 static PyMethodDef EmbMethods[] =
00226 {
00227     {"bn_print", Print, METH_VARARGS, "Print string to Beesnest buffer"},
00228     {"bn_get_hdr", GetRequestHeader, METH_VARARGS, "Return a HTTP request header"},
00229     {"bn_get_var", GetRequestVariable, METH_VARARGS, "Return a HTTP request variable"},
00230     {"bn_set_var", SetRequestVariable, METH_VARARGS, "Set a HTTP request variable"},
00231     {"bn_get_vars", GetRequestVarsNamesList, METH_VARARGS, "Return all HTTP request variables"},
00232     {"bn_set_hdr", SetResponseHeader, METH_VARARGS, "Set HTTP response header"},
00233     {"bn_set_cookie", SetResponseCookie, METH_VARARGS, "Set HTTP response cookie"},
00234     {"bn_clear", Clear, METH_VARARGS, "Clear the response"},
00235     {"bn_flush", Flush, METH_VARARGS, "Flush the response"},
00236     {"bn_adapter", GetAdapter, METH_VARARGS, "Get an adapter ID by name"},
00237     {"bn_free", ReleaseAdapter, METH_VARARGS, "Release an adapter by ID"},
00238     {"bn_read", Read, METH_VARARGS, "Read from adapter"},
00239     {"bn_write", Write, METH_VARARGS, "Write to adapter"},
00240     {"exit", Exit, METH_VARARGS, "Terminate the script"},
00241     {NULL, NULL, 0, NULL}
00242 };
00243 
00244 /*============================================================================*/
00245 
00246 
00247 int BnPython::counter = 0;
00248 map<int, BnPython*> BnPython::mPointers;
00249 
00250 /*
00251 Static function to get a BnPython pointer from an int.
00252 This is a multi-thread function (using one static object),
00253 but it should be OK also without using a Mutex.
00254 */
00255 BnPython* BnPython::GetPointer (int num)
00256 {
00257     map<int, BnPython*>::const_iterator itr = mPointers.find (num);
00258     if (itr == mPointers.end ())
00259     {
00260         PyErr_SetString(PyExc_ValueError,
00261             "First argument to bn_XXX function is not valid");
00262         return NULL;
00263     }
00264     return (itr->second);
00265 }
00266 
00267 BnPython::BnPython (const char* name, bool (*pGetParam)(const char*, char*, int))
00268 :pRes (NULL), pReq (NULL), pSet (NULL), nException (0)
00269 {
00270     sName = name;
00271     pfGetParam = pGetParam;
00272     nPointerCell = ++counter;
00273     mPointers[nPointerCell] = this;
00274 
00275     PyEval_AcquireLock();
00276     oTS = Py_NewInterpreter();
00277 
00278     /* This function initialize the BnPython module, and set the "self" argument
00279         to the value of nPointerCell */
00280     Py_InitModule4("BnPython", EmbMethods, "Beesnest-Python Functions",
00281         Py_BuildValue ("i", nPointerCell), PYTHON_API_VERSION);
00282 
00283     PyRun_SimpleString("import sys\nimport cStringIO");
00284     PyRun_SimpleString("from BnPython import *");
00285 
00286     PyThreadState_Swap(NULL);
00287     PyEval_ReleaseLock();
00288 }
00289 
00290 
00291 BnPython::~BnPython ()
00292 {
00293     Stored ();
00294     mPointers.erase (nPointerCell);
00295 
00296     PyEval_AcquireLock();
00297     PyThreadState_Swap(oTS);
00298     Py_EndInterpreter(oTS);
00299     PyEval_ReleaseLock();
00300 }
00301 
00302 void BnPython::Stored ()
00303 {
00304     ReleaseAdapters ();
00305     sBuffer.clear ();
00306 }
00307 
00308 
00309 void BnPython::Prepare (IdcRequest* preq, IdcResponse* pres, IdcAdaptersSet* pset)
00310 {
00311     pReq = preq;
00312     pRes = pres;
00313     pSet = pset;
00314 }
00315 
00316 
00317 bool BnPython::Process (BufferHolder code, BufferHolder& result, int size_limit)
00318 {
00319     bool ret_val = true;
00320     nSizeLimit = size_limit;
00321     sBuffer.clear ();
00322     if (code.empty ()) return false;
00323 
00324     bExit = false;
00325 
00326     string tmp (code.pointer, code.size);
00327     int place;
00328     while ((place = tmp.find ("\r")) != string::npos)
00329         tmp.replace (place, 1, "");
00330 
00331     PyEval_AcquireLock();
00332     PyThreadState_Swap(oTS);
00333 
00334     PyRun_SimpleString("sys.stdout = cStringIO.StringIO()\nsys.stderr = cStringIO.StringIO()");
00335 
00336     ret_val = PyRun_SimpleString(tmp.c_str ()) > -1;
00337     if (!ret_val && !bExit)     /* if bExit don't need to print a message. */
00338         PyRun_SimpleString("bn_print ('\\n<P><PRE>\\n', sys.stderr.getvalue(), '\\n</PRE></P>\\n')");
00339 
00340     PyRun_SimpleString("bn_print (sys.stdout.getvalue())");
00341     PyRun_SimpleString("sys.stdout.close()\nsys.stderr.close()");
00342 
00343     PyThreadState_Swap(NULL);
00344     PyEval_ReleaseLock();
00345 
00346     ReleaseAdapters ();
00347     /* Check if need to throw an exception to Beesnest. */
00348     if (nException != 0) throw nException;
00349     result.set (sBuffer.c_str ());
00350     return ret_val || bExit;
00351 }
00352 
00353 void BnPython::ReleaseAdapters ()
00354 {
00355     if (pSet)
00356     {
00357         for (set<unsigned int>::iterator itr = oAdaptersList.begin ();
00358             itr != oAdaptersList.end (); ++itr)
00359             pSet->AdapterDone (*itr);
00360 
00361     }
00362     oAdaptersList.clear ();
00363 }
00364 
00365 bool BnPython::CheckSizeLimit ()
00366 {
00367     if (nSizeLimit == 0 || sBuffer.size ()  <  nSizeLimit)
00368         return true;
00369     PyErr_SetString(PyExc_SystemError, "Reached the buffer size limit");
00370     return false;
00371 }
00372 

Generated on Mon Oct 11 2010 16:23:24 for Beesnest by  doxygen 1.7.2