Exemple #1
0
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;
}
Exemple #2
0
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);
}
Exemple #3
0
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;
}
Exemple #4
0
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;
}
Exemple #5
0
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;
}