helpers.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. #include <dlfcn.h>
  2. #include <dirent.h>
  3. #include "helpers.h"
  4. #include "callback.h"
  5. #include "plugin.h"
  6. /////////////////////////////////////////////////////////////////////////////
  7. // {75ed2211-0a25-4a55-962b-31d3b0e6123a}
  8. DEFINE_UUID(UUID_REST_PLUGIN,
  9. 0x75ed2211, 0x0a25, 0x4a55, 0x96, 0x2b, 0x31, 0xd3, 0xb0, 0xe6, 0x12, 0x3a);
  10. /////////////////////////////////////////////////////////////////////////////
  11. typedef struct _PLUGIN
  12. {
  13. std::string sName;
  14. void *hLib;
  15. }PLUGIN;
  16. /////////////////////////////////////////////////////////////////////////////
  17. static std::vector<FILEREQUEST> g_afr;
  18. static std::vector<PLUGIN> g_aPlugins;
  19. /////////////////////////////////////////////////////////////////////////////
  20. static bool _IsSharedLib(const char *pszFilename)
  21. {
  22. char *pSave = nullptr, szFilename[PATH_MAX], *pszTok;
  23. strcpy(szFilename, pszFilename);
  24. if((pszTok = strtok_r(szFilename, ".", &pSave)))
  25. {
  26. while((pszTok = strtok_r(nullptr, ".", &pSave)))
  27. {
  28. if(!strcmp(pszTok, "so"))
  29. return true;
  30. }
  31. }
  32. return false;
  33. }
  34. /////////////////////////////////////////////////////////////////////////////
  35. int LoadPlugins(const char *pszRootDir, struct _u_instance *pInst, json_error_t &rJerr, void *pCtx)
  36. {
  37. DIR *d;
  38. int nLoaded = 0;
  39. struct dirent *dir;
  40. char szPluginDir[PATH_MAX + 32];
  41. char szPluginLib[PATH_MAX + 32 + 256];
  42. sprintf(szPluginDir, "%s/plugin", pszRootDir);
  43. if((d = opendir(szPluginDir)))
  44. {
  45. while((dir = readdir(d)))
  46. {
  47. if((dir->d_type == DT_REG) &&
  48. _IsSharedLib(dir->d_name))
  49. {
  50. sprintf(szPluginLib, "%s/plugin/%s", pszRootDir, dir->d_name);
  51. void *hLib = dlopen(szPluginLib, RTLD_NOW);
  52. if(hLib)
  53. {
  54. PFN_GETPLUGININFO GetPluginInfo = (PFN_GETPLUGININFO)dlsym(hLib, "GetPluginInfo");
  55. if(GetPluginInfo)
  56. {
  57. const REST_PLUGIN_INFO *ppi = nullptr;
  58. if((ppi = GetPluginInfo()))
  59. {
  60. if(!_uuid_compare(&UUID_REST_PLUGIN, &ppi->signature))
  61. {
  62. PLUGIN plugin;
  63. plugin.sName = ppi->pszPluginName;
  64. plugin.hLib = hLib;
  65. g_aPlugins.push_back(plugin);
  66. for(size_t i = 0; i < ppi->nHandlerCnt; ++i)
  67. {
  68. const REST_REQUEST_HANDLER &rh = ppi->handler[i];
  69. PFN_REST_REQUEST_HANDLER RequestHandler = (PFN_REST_REQUEST_HANDLER)dlsym(hLib, rh.pszFunctionName);
  70. if(RequestHandler)
  71. {
  72. if(ulfius_add_endpoint_by_val(pInst, rh.pszMethod, rh.pszVUrl, nullptr, 0, RequestHandler, pCtx) == U_OK)
  73. ++nLoaded;
  74. }
  75. }
  76. }
  77. else
  78. {
  79. dlclose(hLib);
  80. }
  81. }
  82. else
  83. {
  84. dlclose(hLib);
  85. }
  86. }
  87. else
  88. {
  89. dlclose(hLib);
  90. }
  91. }
  92. }
  93. }
  94. closedir(d);
  95. }
  96. return nLoaded;
  97. }
  98. /////////////////////////////////////////////////////////////////////////////
  99. void UnloadPlugins(void)
  100. {
  101. for(PLUGIN &p : g_aPlugins)
  102. {
  103. if(p.hLib)
  104. dlclose(p.hLib);
  105. }
  106. g_aPlugins.clear();
  107. }
  108. /////////////////////////////////////////////////////////////////////////////
  109. int InitializeStaticFiles(const char *pszRootDir, struct _u_instance *pInst, json_error_t &rJerr)
  110. {
  111. int nRet = 0;
  112. char szFilename[PATH_MAX + 32];
  113. sprintf(szFilename, "%s/staticfiles.json", pszRootDir);
  114. if(FileExist(szFilename))
  115. {
  116. CJson_t jtRoot(json_load_file(szFilename, JSON_REJECT_DUPLICATES, &rJerr)); // new reference!
  117. if(jtRoot.IsValid())
  118. {
  119. const char *pszVal;
  120. bool bVal;
  121. if(!jtRoot.IsArray())
  122. {
  123. ETRACE("staticfiles.json contains no array!\n");
  124. return -1;
  125. }
  126. for(size_t i = 0; i < json_array_size(jtRoot); i++)
  127. {
  128. FILEREQUEST fr;
  129. CJson_t jtArr(json_array_get(jtRoot, i), false); // borrowed reference!
  130. if(jtArr.IsValid())
  131. {
  132. if(!jtArr.IsObject())
  133. {
  134. ETRACE("staticfiles.json: element %zu is no object!\n", i);
  135. return -1;
  136. }
  137. json_t *pjtMethod = json_object_get(jtArr, "method");
  138. pszVal = json_string_value(pjtMethod);
  139. fr.strMethod = pszVal;
  140. json_t *pjtUrl = json_object_get(jtArr, "URL");
  141. pszVal = json_string_value(pjtUrl);
  142. fr.strURL = pszVal;
  143. json_t *pjtFilename = json_object_get(jtArr, "fileName");
  144. pszVal = json_string_value(pjtFilename);
  145. sprintf(szFilename, "%s/%s", pszRootDir, pszVal);
  146. fr.strFilename = szFilename;
  147. json_t *pjtContentType = json_object_get(jtArr, "contentType");
  148. pszVal = json_string_value(pjtContentType);
  149. fr.strContentType = pszVal;
  150. json_t *pjtIsString = json_object_get(jtArr, "isString");
  151. bVal = json_boolean_value(pjtIsString);
  152. fr.bString = bVal;
  153. fr.pfnCallback = &FileBodyResponseCallback;
  154. g_afr.push_back(fr);
  155. }
  156. else
  157. {
  158. ETRACE("Error!\n");
  159. return -1;
  160. }
  161. }
  162. }
  163. else
  164. {
  165. if(rJerr.column == -1 || rJerr.line == -1)
  166. {
  167. TRACE("staticfiles.json: no static files configured.\n");
  168. return 0;
  169. }
  170. else
  171. {
  172. ETRACE("%s: line %d, column %d: %s.\n", szFilename, rJerr.line, rJerr.column, rJerr.text);
  173. return -1;
  174. }
  175. }
  176. }
  177. else
  178. {
  179. // TRACE("No static files found.\n");
  180. return 0;
  181. }
  182. // Endpoint list declaration
  183. for(auto it = g_afr.begin(); it != g_afr.end(); it++)
  184. {
  185. FILEREQUEST &rfr = *it;
  186. if(ulfius_add_endpoint_by_val(pInst, rfr.strMethod.c_str(), rfr.strURL.c_str(), nullptr, 0, rfr.pfnCallback, &rfr) != U_OK)
  187. {
  188. ETRACE("Error adding endpoint for URL '%s'!\n", rfr.strURL.c_str());
  189. return -1;
  190. }
  191. else
  192. {
  193. nRet++;
  194. }
  195. }
  196. return nRet;
  197. }