helpers.cpp 5.5 KB

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