Пример #1
0
int Startup(const char *config, streamsize nbytes) {
  PLUGIN_INFO("startup");
  g_plugin = SimplePlugin::CreatePlugin();

  if(!g_plugin) {
    PLUGIN_INFO("creation failed");
    return -1;
  }

  if(!g_plugin->OnStartup(config, nbytes)) {
    PLUGIN_ERROR("startup failed");
    SimplePlugin::DestroyPlugin(g_plugin);
    g_plugin = nullptr;
    return -2;
  }

  g_running = true;
  g_running = g_thread.Initialize(&PluginLoop, nullptr);

  if(!g_running) {
    PLUGIN_ERROR("thread start failed");
  }

  return g_running ? 0 : -1;
}
Пример #2
0
int PluginLoop(void*){

		WatchHandle watch = CreateWatch("*", "*", "*");

		while(running){

				Notification notif;
				if(GetNotification(&notif, 0)){
						PLUGIN_INFO("notification received: %d.\n", notif.type);
						int res = 0;

						switch (notif.type) {
								case kShutdown:
										running = false;
										break;
								case kWatch:
										PluginInfo info;
										res = GetPluginInfo(notif.content.watch.plugin, &info);
										PLUGIN_INFO("plugin %s(%s) available\n", info.name, info.version);
										if(watch == notif.content.watch.handle && notif.content.watch.plugin_state == kPluginAvailable) {
												Connect(notif.content.watch.plugin);
										}
										break;
								default:
										break;
						}
						// process notification
				}
		}
		return 0;
}
Пример #3
0
bool RestClientPluginTest::OnStartup(const char* config, streamsize nbytes) {
	bool result = RegisterCommand(&m_command);
	if(!result) {
		PLUGIN_INFO("failed to register %s", m_command.Name());
	}
	return result;
}
Пример #4
0
void OnConnected(TCPServer::Handle handle, const Base::Socket::Address &address,
                 void *context) {
  PLUGIN_INFO("connection established %d. ip %s", handle,
              Base::Socket::Print(address));
  GatePlugin *this_ = static_cast<GatePlugin *>(context);
  this_->AddConnection(handle, address);
}
Пример #5
0
void OnDisconnected(TCPServer::Handle handle, TCPServer::CloseReason reason,
                    const Base::Socket::Address &address, void *context) {
  PLUGIN_INFO("disconnected %d. reason %s. ip %s", handle,
              TCPServer::ToString(reason), Base::Socket::Print(address));
  GatePlugin *this_ = static_cast<GatePlugin *>(context);
  this_->RemConnection(handle);
}
Пример #6
0
bool GatePlugin::Disconnect(TCPServer::Handle id) {
  if(!m_users->IsConnected(id)) {
    PLUGIN_ERROR("not connected %d.", id);
    return false;
  }
  PLUGIN_INFO("closing connection id: %d", id);
  m_conn->Close(id, TCPServer::CloseReason::kRESTfulAPI);
  return true;
}
Пример #7
0
ret_t 
cherokee_handler_zeromq_configure (cherokee_config_node_t *conf,
								   cherokee_server_t *srv,
								   cherokee_module_props_t **_props)
{
	ret_t							ret;
	cherokee_list_t				 *i;
	cherokee_handler_zeromq_props_t *props;
	cherokee_plugin_info_t		  *info = NULL;
	
	/* Instance a new property object
	 */
	if (*_props == NULL) {
		CHEROKEE_NEW_STRUCT (n, handler_zeromq_props);

		cherokee_handler_props_init_base (HANDLER_PROPS(n), 
						  MODULE_PROPS_FREE(props_free));
		cherokee_buffer_init (&n->endpoint);
		n->io_threads = 1;
		CHEROKEE_MUTEX_INIT (&n->mutex, CHEROKEE_MUTEX_FAST);

		*_props = MODULE_PROPS(n);
	}

	props = PROP_ZEROMQ(*_props);
	
	/* Voodoo to get our own backend gzipper
	 */
	ret = cherokee_plugin_loader_get (&srv->loader, "gzip", &info);
	if (ret != ret_ok) {
		return ret;
	}

	/* Parse the configuration tree
	 */
	cherokee_config_node_foreach (i, conf) {
		cherokee_config_node_t *subconf = CONFIG_NODE(i);

		if (equal_buf_str (&subconf->key, "endpoint")) {
			cherokee_buffer_clean (&props->endpoint);
			cherokee_buffer_add_buffer (&props->endpoint, &subconf->val);
		} else if (equal_buf_str (&subconf->key, "io_threads")) {
			props->io_threads = atoi(subconf->val.buf);
		} else if (equal_buf_str (&subconf->key, "encoder") && info->configure) {
			encoder_func_configure_t configure = info->configure;
			props->encoder_props = NULL;

			ret = configure (subconf, srv, (cherokee_module_props_t **)&props->encoder_props);
			if (ret != ret_ok) {
				return ret;
			}

			props->encoder_props->instance_func = PLUGIN_INFO(info)->instance;
		}

	}
Пример #8
0
void GatePlugin::RemConnection(TCPServer::Handle handle) {

  redisReply *reply =
      static_cast<redisReply *>(redisCommand(m_redis, "DEL user:%llu", handle));
  if(!reply) {
    PLUGIN_ERROR("redis command failed");
    return;
  }
  PLUGIN_INFO("DEL: %s", reply->str);
  freeReplyObject(reply);
}
Пример #9
0
bool GatePlugin::RedisConnectBlocking(const char *hostname, u16 port) {
  m_redis = redisConnect(hostname, port);
  if(!m_redis) {
    PLUGIN_ERROR("redis: can't allocate redis");
    return false;
  }
  if(m_redis->err) {
    PLUGIN_ERROR("redis: %s", m_redis->errstr);
    return false;
  }

  PLUGIN_INFO("redis connected at %s:%d", hostname, port);
  return true;
}
Пример #10
0
void GatePlugin::AddConnection(TCPServer::Handle handle,
                               const Base::Socket::Address &address) {
  redisReply *reply = static_cast<redisReply *>(
      // redisCommand(m_redis, "SET user:%llu data", handle));
      redisCommand(m_redis, "HMSET user:%llu"
                            "id %llu"
                            "name user_name",
                   handle, handle));
  if(!reply) {
    PLUGIN_ERROR("redis command failed");
    return;
  }
  PLUGIN_INFO("HMSET: %s", reply->str);

  freeReplyObject(reply);
}
Пример #11
0
void SimplePlugin::Recv(ConnectionHandle conn, void *buffer,
                        unsigned int nbytes,
                        std::function<void(void *, unsigned int)> func) {
  BASE_ASSERT(conn != 0);
  u32 nrecv = 0;
  int data_received = 0;
  void *work_buffer = buffer;
  unsigned int work_buffer_size = nbytes;

  int total_available = GetTotalRecvAvailable(conn);

  static const unsigned int kBufferTooSmall = -2;

  // only process limited amount of data in this call
  while(data_received < total_available) {
    do {
      if(nrecv == kBufferTooSmall) {
        // previous recv call failed because buffer was too small. allocating
        // bigger buffer.
        work_buffer_size = GetRecvAvailable(conn);
        work_buffer = malloc(work_buffer_size);
        PLUGIN_INFO("recv failed - buffer too small. %d expecting %d.",
                    work_buffer_size, work_buffer_size);
      }

      //			((char*)work_buffer)[work_buffer_size-1] = 0;

      nrecv = ::Recv(conn, work_buffer, work_buffer_size /*-1*/);

      if(0 < nrecv) {
        func(work_buffer, nrecv);
        data_received += nrecv;
      }

      if(work_buffer != buffer) {
        // free temp buffer and switch back to input buffer.
        free(work_buffer);
        work_buffer = buffer;
        work_buffer_size = nbytes;
      }

    } while(nrecv == kBufferTooSmall); // if buffer was too small try receiving
                                       // with bigger buffer.
  }
}
Пример #12
0
ret_t
cherokee_handler_init_base (cherokee_handler_t             *hdl,
                            void                           *conn,
                            cherokee_handler_props_t       *props,
                            cherokee_plugin_info_handler_t *info)
{
	/* Init the base class
	 */
	cherokee_module_init_base (MODULE(hdl), MODULE_PROPS(props), PLUGIN_INFO(info));

	/* Pure virtual methods
	 */
	hdl->read_post     = NULL;
	hdl->add_headers   = NULL;
	hdl->step          = NULL;

	/* Parent reference
	 */
	hdl->connection    = conn;

	return ret_ok;
}
Пример #13
0
ret_t
cherokee_validator_init_base (cherokee_validator_t             *validator,
			      cherokee_validator_props_t       *props,
			      cherokee_plugin_info_validator_t *info)
{
	cherokee_module_init_base (MODULE(validator), MODULE_PROPS(props), PLUGIN_INFO(info));

	validator->check = NULL;

	cherokee_buffer_init (&validator->user);
	cherokee_buffer_init (&validator->passwd);
	cherokee_buffer_init (&validator->realm);
	cherokee_buffer_init (&validator->response);
	cherokee_buffer_init (&validator->uri);
	cherokee_buffer_init (&validator->qop);
	cherokee_buffer_init (&validator->nonce);
	cherokee_buffer_init (&validator->cnonce);
	cherokee_buffer_init (&validator->algorithm);
	cherokee_buffer_init (&validator->nc);

	return ret_ok;
}
Пример #14
0
bool GatePlugin::OnStartup(const char *config, streamsize nbytes) {

  if(!RegisterCommand(&m_list_cmd) || !RegisterCommand(&m_disconnect_cmd) ||
     !RegisterCommand(&m_logout_cmd)) {
    return false;
  }
  if(!config || nbytes == 0) {
    PLUGIN_ERROR("no config");
    return false;
  }

  tinyxml2::XMLDocument doc;
  tinyxml2::XMLError err = doc.Parse(config, nbytes);

  if(err != tinyxml2::XML_SUCCESS) {
    PLUGIN_ERROR("problem parsing config: %s(%d)", doc.ErrorName(), err);
    return false;
  }

  u16 port = 0;
  u32 max_connections = 0;
  std::string redis_hostname("localhost");
  u16 redis_port = 6379;
  {
    tinyxml2::XMLElement *root = doc.RootElement();
    if(root->Attribute("port")) {
      port = root->IntAttribute("port");
      PLUGIN_INFO("port read %d", port);
    } else {
      PLUGIN_WARN("no port specified, defaulting to 0");
    }

    if(!root->Attribute("max_connections")) {
      PLUGIN_ERROR("maximum connection count not specified");
      return false;
    }
    max_connections = root->IntAttribute("max_connections");
    PLUGIN_INFO("maximum number of connections: %d", max_connections);

    if(max_connections == 0) {
      PLUGIN_ERROR("invalid number of max connections: %d", max_connections);
      return false;
    }

    tinyxml2::XMLElement *redis = root->FirstChildElement("redis");
    if(redis && redis->Attribute("hostname") && redis->Attribute("port")) {
      redis_hostname = redis->Attribute("hostname");
      redis_port = redis->IntAttribute("port");
    } else {
      PLUGIN_WARN("failed to load redis config");
    }
  }

  m_users = new Users(max_connections);
  if(m_users == nullptr) {
    PLUGIN_ERROR("problem creating users data");
    return false;
  }

  TCPServer::Callbacks callbacks = {Link::Gate::OnConnected,
                                    Link::Gate::OnDisconnected,
                                    Link::Gate::OnMessage};

  m_conn = new TCPServer(max_connections, callbacks, this);

  if(!m_conn->CreateListenSocket(port)) {
    delete m_conn;
    PLUGIN_ERROR("failed to create listen port");
    return false;
  }

  PLUGIN_INFO("gate listening on port: %d", port);

  RedisConnectBlocking(redis_hostname.c_str(), redis_port);

  return true;
}
Пример #15
0
void OnMessage(TCPServer::Handle handle, void *buffer, u32 nbytes,
               void *context) {
  PLUGIN_INFO("data on connection %d. bytes %d", handle, nbytes);
  GatePlugin *this_ = static_cast<GatePlugin *>(context);
  this_->HandleMessage(handle, buffer, nbytes);
}
Пример #16
0
void GatePlugin::HandleMessage(TCPServer::Handle handle, void *data,
                               u32 nbytes) {
  // Connection& conn = m_users->GetConnection(handle);

  ProtobufStream stream(data, nbytes);
  gate::ClientMessage msg;
  if(!msg.ParseFromIstream(&stream)) {
    PLUGIN_ERROR("protocol error");
    m_conn->Close(handle, TCPServer::CloseReason::kProtocolError);
    return;
  }
  gate::ClientMessage::Type type = msg.type();
  const char *protoc = msg.protocol_version().c_str();
  PLUGIN_INFO("message type: %d, protocol version: %s", type, protoc);

  switch(type) {
  case gate::ClientMessage::kLogin: {
    const gate::Login &login = msg.login();
    gate::ServerMessage response;
    response.set_type(gate::ServerMessage::kLoggedIn);
    response.set_protocol_version(kProtocolVersion);
    gate::LoggedIn &logged_in = *response.mutable_logged_in();
    logged_in.set_index(login.index());

    index_t index = m_users->AddUser(handle, login.username().c_str());
    logged_in.set_user_id(index);
    // todo(kstasik): validate index. send it back.
    if(index == kInvalidUserHandle) {
      PLUGIN_ERROR("problem logging in '%s'", login.username().c_str());
    }
    PLUGIN_INFO("user '%s' logged in", login.username().c_str());
    std::string serialized;
    response.SerializeToString(&serialized);
    if(!m_conn->Send(handle, static_cast<const void *>(serialized.c_str()),
                     serialized.length())) {
      m_conn->Close(handle,
                    TCPServer::CloseReason::kProtocolError); // todo(kstasik):
                                                             // new error type
    }
  } break;
  case gate::ClientMessage::kLogout: {
    const gate::Logout &logout = msg.logout();
    gate::ServerMessage response;
    response.set_type(gate::ServerMessage::kLoggedOut);
    response.set_protocol_version(
        kProtocolVersion); // todo(kstasik): refactor protoc version
    gate::LoggedOut &logged_out = *response.mutable_logged_out();
    logged_out.set_user_id(logout.user_id());
    if(!m_users->RemUser(handle, logout.user_id())) {
      PLUGIN_ERROR("problem logging out handle: %d index %d", handle,
                   logout.user_id());
      // todo(kstasik): handle error
    } else {
      PLUGIN_INFO("handle %d index %d logged out", handle, logout.user_id());
    }
    std::string serialized;
    response.SerializeToString(&serialized);
    if(!m_conn->Send(handle, static_cast<const void *>(serialized.c_str()),
                     serialized.length())) {
      m_conn->Close(handle,
                    TCPServer::CloseReason::kProtocolError); // todo(kstasik):
                                                             // new error type
    }
  } break;
  default:
    break;
  }
}
Пример #17
0
int PluginLoop(void *) {
  PLUGIN_INFO("thread started");
  g_plugin->OnThreadEntry();

  unsigned int last_time = Base::Time::GetTimeMs();
  while(g_running) {
    Notification notif;
    if(GetNotification(&notif, g_plugin->IdleDt())) {
      // PLUGIN_INFO("notification received: %d.", notif.type);
      g_plugin->OnNotification(notif);
      switch(notif.type) {
      case kShutdown:
        g_plugin->OnShutdown(notif.content.shutdown);
        g_running = false;
        break;
      case kWatch: {
        PluginInfo info;
        if(0 == GetPluginInfo(notif.content.watch.plugin, &info)) {
          PLUGIN_INFO("watch plugin match %s(%s) for %p", info.name,
                      info.version, notif.content.watch.handle);
        } else {
          PLUGIN_WARN("unknown plugin match for %p",
                      notif.content.connection.endpoint);
        }
        g_plugin->OnWatchMatch(notif.content.watch);
        break;
      }
      case kConfigChanged:
        g_plugin->OnConfigChange(notif.content.config);
        break;
      case kEstablished: {
        PluginInfo info;
        if(0 == GetPluginInfo(notif.content.connection.endpoint, &info)) {
          PLUGIN_INFO("connected to %s(%s)", info.name, info.version);
        } else {
          PLUGIN_WARN("connected to unknown plugin %p",
                      notif.content.connection.endpoint);
        }
        g_plugin->OnConnected(notif.content.connection);
        break;
      }
      case kConnected: {
        PluginInfo info;
        if(0 == GetPluginInfo(notif.content.connection.endpoint, &info)) {
          PLUGIN_INFO("plugin connected %s(%s)", info.name, info.version);
        } else {
          PLUGIN_WARN("unknown plugin connected %p",
                      notif.content.connection.endpoint);
        }
        g_plugin->OnPluginConnected(notif.content.connection);
        break;
      }
      case kDisconnected:
        PluginInfo info;
        if(0 == GetPluginInfo(notif.content.connection.endpoint, &info)) {
          PLUGIN_INFO("plugin disconnected %s(%s)", info.name, info.version);
        } else {
          PLUGIN_WARN("unknown plugin disconnected %p",
                      notif.content.connection.endpoint);
        }
        g_plugin->OnDisconnected(notif.content.connection);
        break;
      case kRecvReady:
        g_plugin->OnRecvReady(notif.content.connection);
      default:
        break;
      }
    }

    unsigned int now = Base::Time::GetTimeMs();
    unsigned int dt = now - last_time;
    g_plugin->OnUpdate(dt);
    last_time = now;
  }

  g_plugin->OnThreadExit();
  PLUGIN_INFO("thread exiting");
  return 0;
}