bool Plugin::loadPlugin(const std::string name, const std::string file) { LIBRARY_HANDLE lhandle = NULL; void (*fhandle)(mineserver_pointer_struct*) = NULL; if (!file.empty()) { LOG(INFO, "Plugin", "Loading plugin `" + name + "' (`" + file + "')..."); struct stat st; int statr = stat(file.c_str(), &st); if ((statr == 0) && !(st.st_mode & S_IFDIR)) { lhandle = LIBRARY_LOAD(file.c_str()); } else { LOG(INFO, "Plugin", "Could not find `" + file + "', trying `" + file + LIBRARY_EXTENSION + "'."); statr = stat((file + LIBRARY_EXTENSION).c_str(), &st); if ((statr == 0) && !(st.st_mode & S_IFDIR)) { lhandle = LIBRARY_LOAD((file + LIBRARY_EXTENSION).c_str()); } else { LOG(INFO, "Plugin", "Could not find `" + file + LIBRARY_EXTENSION + "'!"); return false; } } } else { LOG(INFO, "Plugin", "Loading plugin `" + name + "' (built in)..."); lhandle = LIBRARY_SELF(); } if (lhandle == NULL) { LOG(INFO, "Plugin", "Could not load plugin `" + name + "'!"); LOG(INFO, "Plugin", LIBRARY_ERROR()); return false; } m_libraryHandles[name] = lhandle; fhandle = (void (*)(mineserver_pointer_struct*)) LIBRARY_SYMBOL(lhandle, (name + "_init").c_str()); if (fhandle == NULL) { LOG(INFO, "Plugin", "Could not get init function handle!"); unloadPlugin(name); return false; } fhandle(&plugin_api_pointers); return true; }
Plugin * Plugin::open_plugin (Application * appstate, const std::string filename) { typedef Plugin * (*Plugin_Main) (Application *, Handle *); if (filename.length() == 0) return NULL; // Get a handle to the shared library we're attempting to open. Handle * platform = new Handle; if ((platform->handle = LIBRARY_OPEN (filename.c_str())) == NULL) { fprintf (stderr, "%s\n", LIBRARY_ERROR()); exit(1); } // Grab the main method from the plugin so we can execute to get an object back. Plugin_Main plugin_main; if ((plugin_main = (Plugin_Main)LIBRARY_SYM(platform->handle, "PluginFactoryCreate")) == NULL) { fprintf (stderr, "%s\n", LIBRARY_ERROR()); exit(1); } // Execute the method, return an object, and basically go on our merry way. return plugin_main (appstate, platform); }
bool Plugin::loadExternal(const std::string name, const std::string file) { LIBRARY_HANDLE lhandle = NULL; void (*fhandle)(Mineserver*) = NULL; Mineserver::get()->screen()->log("Loading plugin "+name+" ("+file+")..."); struct stat st; if(stat(file.c_str(), &st) != 0) { Mineserver::get()->screen()->log("Could not find "+file+"!"); return false; } lhandle = LIBRARY_LOAD(file.c_str()); if (lhandle == NULL) { Mineserver::get()->screen()->log("Could not load "+file+"!"); Mineserver::get()->screen()->log(LIBRARY_ERROR()); return false; } m_libraryHandles[name] = lhandle; fhandle = (void (*)(Mineserver*)) LIBRARY_SYMBOL(lhandle, (name+"_init").c_str()); if (fhandle == NULL) { Mineserver::get()->screen()->log("Could not get init function handle!"); unloadExternal(name); return false; } fhandle(Mineserver::get()); return true; }
bool Plugin::loadPlugin(const std::string& name, const std::string& path, std::string alias) { LIBRARY_HANDLE lhandle = NULL; pfms fhandle = NULL; if (name.empty() || (name.find('/') != std::string::npos) || (name.find('\\') != std::string::npos)) { LOG(INFO, "Plugin", "Invalid name: " + name); return false; } if (alias.empty()) { alias = name; } if (!path.empty()) { std::string file; file = path + '/' + name + LIBRARY_EXTENSION; struct stat st; int statr = stat(file.c_str(), &st); if ((statr == 0) && !(st.st_mode & S_IFDIR)) { LOG(INFO, "Plugin", "Loading: " + file); lhandle = LIBRARY_LOAD(file.c_str()); } else { LOG(INFO, "Plugin", "Could not find: " + file); return false; } } else { LOG(INFO, "Plugin", "Loading built-in: " + name); lhandle = LIBRARY_SELF(); } if (lhandle == NULL) { LOG(INFO, "Plugin", "Could not load: " + name); LOG(INFO, "Plugin", LIBRARY_ERROR()); return false; } m_libraryHandles[alias] = lhandle; *reinterpret_cast<void**>(&fhandle) = (void*)LIBRARY_SYMBOL(lhandle, (name + "_init").c_str()); if (fhandle == NULL) { LOG(INFO, "Plugin", "Could not get init function handle!"); unloadPlugin(alias); return false; } fhandle(&plugin_api_pointers); return true; }
static void do_updates(multiple_query_ctx_t *query_ctx) { char *iter = (char *) (query_ctx->query_param + 1); size_t sz = MAX_UPDATE_QUERY_LEN(query_ctx->num_result); // Sort the results to avoid database deadlock. qsort(query_ctx->res, query_ctx->num_result, sizeof(*query_ctx->res), compare_items); query_ctx->query_param->param.command = iter; query_ctx->query_param->param.nParams = 0; query_ctx->query_param->param.on_result = on_update_result; query_ctx->query_param->param.paramFormats = NULL; query_ctx->query_param->param.paramLengths = NULL; query_ctx->query_param->param.paramValues = NULL; query_ctx->query_param->param.flags = 0; query_ctx->res->random_number = 1 + get_random_number(MAX_ID, &query_ctx->ctx->random_seed); int c = snprintf(iter, sz, UPDATE_QUERY_BEGIN, query_ctx->res->id, query_ctx->res->random_number); if ((size_t) c >= sz) goto error; iter += c; sz -= c; for (size_t i = 1; i < query_ctx->num_result; i++) { query_ctx->res[i].random_number = 1 + get_random_number(MAX_ID, &query_ctx->ctx->random_seed); c = snprintf(iter, sz, UPDATE_QUERY_ELEM, query_ctx->res[i].id, query_ctx->res[i].random_number); if ((size_t) c >= sz) goto error; iter += c; sz -= c; } c = snprintf(iter, sz, UPDATE_QUERY_END); if ((size_t) c >= sz) goto error; if (execute_query(query_ctx->ctx, &query_ctx->query_param->param)) { query_ctx->cleanup = true; send_service_unavailable_error(DB_REQ_ERROR, query_ctx->req); } else query_ctx->num_query_in_progress++; return; error: query_ctx->cleanup = true; LIBRARY_ERROR("snprintf", "Truncated output."); send_error(INTERNAL_SERVER_ERROR, REQ_ERROR, query_ctx->req); }
static void do_updates(multiple_query_ctx_t *query_ctx) { thread_context_t * const ctx = H2O_STRUCT_FROM_MEMBER(thread_context_t, event_loop.h2o_ctx, query_ctx->req->conn->ctx); char *iter = (char *) (query_ctx->query_param + 1); size_t sz = MAX_UPDATE_QUERY_LEN(query_ctx->num_result); // Sort the results to avoid database deadlock. qsort(query_ctx->res, query_ctx->num_result, sizeof(*query_ctx->res), compare_items); query_ctx->query_param->param.command = iter; query_ctx->query_param->param.nParams = 0; query_ctx->query_param->param.on_result = on_update_result; query_ctx->query_param->param.paramFormats = NULL; query_ctx->query_param->param.paramLengths = NULL; query_ctx->query_param->param.paramValues = NULL; query_ctx->query_param->param.flags = 0; query_ctx->res->random_number = get_random_number(MAX_ID, &ctx->random_seed) + 1; int c = snprintf(iter, sz, UPDATE_QUERY_BEGIN, query_ctx->res->id, query_ctx->res->random_number); if ((size_t) c >= sz) goto error; iter += c; sz -= c; for (size_t i = 1; i < query_ctx->num_result; i++) { query_ctx->res[i].random_number = get_random_number(MAX_ID, &ctx->random_seed) + 1; c = snprintf(iter, sz, UPDATE_QUERY_ELEM, query_ctx->res[i].id, query_ctx->res[i].random_number); if ((size_t) c >= sz) goto error; iter += c; sz -= c; } c = snprintf(iter, sz, UPDATE_QUERY_END); if ((size_t) c >= sz) goto error; if (execute_query(ctx, &query_ctx->query_param->param)) send_service_unavailable_error(DB_REQ_ERROR, query_ctx->req); else { query_ctx->num_query_in_progress++; h2o_mem_addref_shared(query_ctx); } return; error: LIBRARY_ERROR("snprintf", "Truncated output."); send_error(INTERNAL_SERVER_ERROR, REQ_ERROR, query_ctx->req); }
static int get_listener_socket(const char *bind_address, uint16_t port) { int ret = -1; char buf[16]; if ((size_t) snprintf(buf, sizeof(buf), "%" PRIu16, port) >= sizeof(buf)) { LIBRARY_ERROR("snprintf", "Truncated output."); return ret; } struct addrinfo *res = NULL; struct addrinfo hints = {.ai_socktype = SOCK_STREAM, .ai_flags = AI_PASSIVE}; const int error_code = getaddrinfo(bind_address, buf, &hints, &res); if (error_code) { LIBRARY_ERROR("getaddrinfo", gai_strerror(error_code)); return ret; } for (const struct addrinfo *iter = res; iter; iter = iter->ai_next) { const int s = socket(iter->ai_family, iter->ai_socktype | SOCK_NONBLOCK | SOCK_CLOEXEC, iter->ai_protocol); if (s == -1) { STANDARD_ERROR("socket"); continue; } #define LOCAL_CHECK_ERRNO(function, ...) \ do { \ const int error_code = (function)(__VA_ARGS__); \ \ if (error_code) { \ print_library_error(__FILE__, __LINE__, #function, errno); \ goto error; \ } \ } while(0) int option = 1; LOCAL_CHECK_ERRNO(setsockopt, s, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option)); LOCAL_CHECK_ERRNO(setsockopt, s, SOL_SOCKET, SO_REUSEPORT, &option, sizeof(option)); LOCAL_CHECK_ERRNO(setsockopt, s, IPPROTO_TCP, TCP_QUICKACK, &option, sizeof(option)); option = H2O_DEFAULT_HANDSHAKE_TIMEOUT_IN_SECS; LOCAL_CHECK_ERRNO(setsockopt, s, IPPROTO_TCP, TCP_DEFER_ACCEPT, &option, sizeof(option)); option = DEFAULT_TCP_FASTOPEN_QUEUE_LEN; LOCAL_CHECK_ERRNO(setsockopt, s, IPPROTO_TCP, TCP_FASTOPEN, &option, sizeof(option)); LOCAL_CHECK_ERRNO(bind, s, iter->ai_addr, iter->ai_addrlen); LOCAL_CHECK_ERRNO(listen, s, INT_MAX); ret = s; break; #undef LOCAL_CHECK_ERRNO error: close(s); } freeaddrinfo(res); if (ret == -1) abort(); return ret; }
static result_return_t on_fortune_result(db_query_param_t *param, PGresult *result) { fortune_ctx_t * const fortune_ctx = H2O_STRUCT_FROM_MEMBER(fortune_ctx_t, param, param); int ret = DONE; const ExecStatusType status = PQresultStatus(result); if (status == PGRES_TUPLES_OK) { const size_t num_rows = PQntuples(result); ret = SUCCESS; for (size_t i = 0; i < num_rows; i++) { fortune_t * const fortune = h2o_mem_alloc_pool(&fortune_ctx->req->pool, sizeof(*fortune)); if (fortune) { memset(fortune, 0, sizeof(*fortune)); fortune->id.base = PQgetvalue(result, i, 0); fortune->id.len = PQgetlength(result, i, 0); fortune->message = h2o_htmlescape(&fortune_ctx->req->pool, PQgetvalue(result, i, 1), PQgetlength(result, i, 1)); fortune->l.next = fortune_ctx->result; fortune_ctx->result = &fortune->l; fortune_ctx->num_result++; if (!i) fortune->data = result; } else { send_error(INTERNAL_SERVER_ERROR, REQ_ERROR, fortune_ctx->req); ret = DONE; if (!i) PQclear(result); break; } } } else if (result) { LIBRARY_ERROR("PQresultStatus", PQresultErrorMessage(result)); send_error(BAD_GATEWAY, DB_ERROR, fortune_ctx->req); PQclear(result); } else { mustache_api_t api = {.sectget = on_fortune_section, .varget = on_fortune_variable, .write = add_iovec}; thread_context_t * const ctx = H2O_STRUCT_FROM_MEMBER(thread_context_t, event_loop.h2o_ctx, fortune_ctx->req->conn->ctx); const size_t iovcnt = MIN(MAX_IOVEC, fortune_ctx->num_result * 5 + 2); const size_t sz = offsetof(iovec_list_t, iov) + iovcnt * sizeof(h2o_iovec_t); char _Alignas(iovec_list_t) mem[sz]; iovec_list_t * const restrict iovec_list = (iovec_list_t *) mem; memset(iovec_list, 0, offsetof(iovec_list_t, iov)); iovec_list->max_iovcnt = iovcnt; fortune_ctx->iovec_list_iter = iovec_list; fortune_ctx->result = sort_fortunes(fortune_ctx->result); if (mustache_render(&api, fortune_ctx, ctx->global_data->fortunes_template)) { fortune_ctx->iovec_list = iovec_list->l.next; set_default_response_param(HTML, fortune_ctx->content_length, fortune_ctx->req); h2o_start_response(fortune_ctx->req, &fortune_ctx->generator); const h2o_send_state_t state = fortune_ctx->iovec_list ? H2O_SEND_STATE_IN_PROGRESS : H2O_SEND_STATE_FINAL; h2o_send(fortune_ctx->req, iovec_list->iov, iovec_list->iovcnt, state); } else send_error(INTERNAL_SERVER_ERROR, REQ_ERROR, fortune_ctx->req); } return ret; }