123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240 |
- #include <dlfcn.h>
- #include <dirent.h>
- #include "helpers.h"
- #include "callback.h"
- #include "plugin.h"
- /////////////////////////////////////////////////////////////////////////////
- // {75ed2211-0a25-4a55-962b-31d3b0e6123a}
- DEFINE_UUID(UUID_REST_PLUGIN,
- 0x75ed2211, 0x0a25, 0x4a55, 0x96, 0x2b, 0x31, 0xd3, 0xb0, 0xe6, 0x12, 0x3a);
- /////////////////////////////////////////////////////////////////////////////
- typedef struct _PLUGIN
- {
- std::string sName;
- std::string sLibPath;
- void *hLib;
- }PLUGIN;
- typedef int (*PFN_REST_REQUEST_HANDLER)(const struct _u_request*, struct _u_response*, void*);
- /////////////////////////////////////////////////////////////////////////////
- static std::vector<FILEREQUEST> g_afr;
- static std::vector<PLUGIN> g_aPlugins;
- /////////////////////////////////////////////////////////////////////////////
- static bool _IsSharedLib(const char *pszFilename)
- {
- char *pSave = nullptr, szFilename[PATH_MAX], *pszTok;
- strcpy(szFilename, pszFilename);
-
- if((pszTok = strtok_r(szFilename, ".", &pSave)))
- {
- while((pszTok = strtok_r(nullptr, ".", &pSave)))
- {
- if(!strcmp(pszTok, "so"))
- return true;
- }
- }
- return false;
- }
- /////////////////////////////////////////////////////////////////////////////
- int LoadPlugins(const char *pszRootDir, struct _u_instance *pInst, json_error_t &rJerr, PCREST_PLUGIN_REQUEST_CONTEXT prc)
- {
- DIR *d;
- int nLoaded = 0;
- struct dirent *dir;
- char szPluginDir[PATH_MAX + 32];
- char szPluginLib[PATH_MAX + 32 + 256];
- sprintf(szPluginDir, "%s/plugin", pszRootDir);
- if((d = opendir(szPluginDir)))
- {
- while((dir = readdir(d)))
- {
- if((dir->d_type == DT_REG) &&
- _IsSharedLib(dir->d_name))
- {
- sprintf(szPluginLib, "%s/plugin/%s", pszRootDir, dir->d_name);
- void *hLib = dlopen(szPluginLib, RTLD_NOW);
- if(hLib)
- {
- PFN_GETPLUGININFO GetPluginInfo = (PFN_GETPLUGININFO)dlsym(hLib, "GetPluginInfo");
-
- if(GetPluginInfo)
- {
- const REST_PLUGIN_INFO *ppi = nullptr;
- if((ppi = GetPluginInfo()))
- {
- if(!_uuid_compare(&UUID_REST_PLUGIN, &ppi->signature))
- {
- PLUGIN plugin;
- plugin.sName = ppi->pszPluginName;
- plugin.sLibPath = szPluginLib;
- plugin.hLib = hLib;
- g_aPlugins.push_back(plugin);
-
- for(size_t i = 0; i < ppi->nHandlerCnt; ++i)
- {
- const REST_REQUEST_HANDLER &rh = ppi->handler[i];
- PFN_REST_REQUEST_HANDLER RequestHandler = (PFN_REST_REQUEST_HANDLER)dlsym(hLib, rh.pszFunctionName);
-
- if(RequestHandler)
- {
- if(ulfius_add_endpoint_by_val(pInst, rh.pszHttpMethod, rh.pszVirtPath, nullptr, 0, RequestHandler, (void*)prc) == U_OK)
- ++nLoaded;
- }
- }
- }
- else
- {
- dlclose(hLib);
- }
- }
- else
- {
- dlclose(hLib);
- }
- }
- else
- {
- dlclose(hLib);
- }
- }
- }
- }
- closedir(d);
- }
- return nLoaded;
- }
- /////////////////////////////////////////////////////////////////////////////
- void UnloadPlugins(void)
- {
- for(PLUGIN &p : g_aPlugins)
- {
- if(p.hLib)
- dlclose(p.hLib);
- }
-
- g_aPlugins.clear();
- }
- /////////////////////////////////////////////////////////////////////////////
- int InitializeStaticFiles(const char *pszRootDir, struct _u_instance *pInst, json_error_t &rJerr)
- {
- int nRet = 0;
- char szFilename[PATH_MAX + 32];
- sprintf(szFilename, "%s/staticfiles.json", pszRootDir);
- if(FileExist(szFilename))
- {
- CJson_t jtRoot(json_load_file(szFilename, JSON_REJECT_DUPLICATES, &rJerr)); // new reference!
- if(jtRoot.IsValid())
- {
- const char *pszVal;
- bool bVal;
- if(!jtRoot.IsArray())
- {
- ETRACE("staticfiles.json contains no array!\n");
- return -1;
- }
- for(size_t i = 0; i < json_array_size(jtRoot); i++)
- {
- FILEREQUEST fr;
- CJson_t jtArr(json_array_get(jtRoot, i), false); // borrowed reference!
- if(jtArr.IsValid())
- {
- if(!jtArr.IsObject())
- {
- ETRACE("staticfiles.json: element %zu is no object!\n", i);
- return -1;
- }
- json_t *pjtMethod = json_object_get(jtArr, "method");
- pszVal = json_string_value(pjtMethod);
- fr.strMethod = pszVal;
- json_t *pjtUrl = json_object_get(jtArr, "URL");
- pszVal = json_string_value(pjtUrl);
- fr.strURL = pszVal;
- json_t *pjtFilename = json_object_get(jtArr, "fileName");
- pszVal = json_string_value(pjtFilename);
- sprintf(szFilename, "%s/%s", pszRootDir, pszVal);
- fr.strFilename = szFilename;
- json_t *pjtContentType = json_object_get(jtArr, "contentType");
- pszVal = json_string_value(pjtContentType);
- fr.strContentType = pszVal;
- json_t *pjtIsString = json_object_get(jtArr, "isString");
- bVal = json_boolean_value(pjtIsString);
- fr.bString = bVal;
- fr.pfnCallback = &FileBodyResponseCallback;
- g_afr.push_back(fr);
- }
- else
- {
- ETRACE("Error!\n");
- return -1;
- }
- }
- }
- else
- {
- if(rJerr.column == -1 || rJerr.line == -1)
- {
- TRACE("staticfiles.json: no static files configured.\n");
- return 0;
- }
- else
- {
- ETRACE("%s: line %d, column %d: %s.\n", szFilename, rJerr.line, rJerr.column, rJerr.text);
- return -1;
- }
- }
- }
- else
- {
- // TRACE("No static files found.\n");
- return 0;
- }
- // Endpoint list declaration
- for(auto it = g_afr.begin(); it != g_afr.end(); it++)
- {
- FILEREQUEST &rfr = *it;
- if(ulfius_add_endpoint_by_val(pInst, rfr.strMethod.c_str(), rfr.strURL.c_str(), nullptr, 0, rfr.pfnCallback, &rfr) != U_OK)
- {
- ETRACE("Error adding endpoint for URL '%s'!\n", rfr.strURL.c_str());
- return -1;
- }
- else
- {
- nRet++;
- }
- }
- return nRet;
- }
|