예제 #1
0
ConnectionPool::ConnectionPool(pjsip_host_port* target,
                               int num_connections,
                               int recycle_period,
                               pj_pool_t* pool,
                               pjsip_endpoint* endpt,
                               pjsip_tpfactory* tp_factory) :
  _target(*target),
  _num_connections(num_connections),
  _recycle_period(recycle_period),
  _pool(pool),
  _endpt(endpt),
  _tpfactory(tp_factory),
  _recycler(NULL),
  _terminated(false),
  _active_connections(0),
  _statistic("connected_sprouts")
{
  LOG_STATUS("Creating connection pool to %.*s:%d", _target.host.slen, _target.host.ptr, _target.port);
  LOG_STATUS("  connections = %d, recycle time = %d seconds", _num_connections, _recycle_period);

  pthread_mutex_init(&_tp_hash_lock, NULL);
  _tp_hash.resize(_num_connections);

  report_sprout_counts();
}
예제 #2
0
/// Set up a new view of the memcached cluster(s).  The view determines
/// how data is distributed around the cluster.
void MemcachedStore::new_view(const std::vector<std::string>& servers,
                              const std::vector<std::string>& new_servers)
{
  LOG_STATUS("Updating memcached store configuration");

  // Create a new view with the new server lists.
  MemcachedStoreView view(_vbuckets, _replicas);
  view.update(servers, new_servers);

  // Now copy the view so it can be accessed by the worker threads.
  pthread_rwlock_wrlock(&_view_lock);

  // Get the list of servers from the view.
  _servers = view.servers();

  // For each vbucket, get the list of read replicas and write replicas.
  for (int ii = 0; ii < _vbuckets; ++ii)
  {
    _read_replicas[ii] = view.read_replicas(ii);
    _write_replicas[ii] = view.write_replicas(ii);
  }

  // Update the view number as the last thing here, otherwise we could stall
  // other threads waiting for the lock.
  LOG_STATUS("Finished preparing new view, so flag that workers should switch to it");
  ++_view_number;

  pthread_rwlock_unlock(&_view_lock);
}
예제 #3
0
파일: sas.cpp 프로젝트: sa4250mnpo70/sprout
bool SAS::Connection::connect_init()
{
  int rc;
  struct sockaddr_in addr;

  LOG_STATUS("Attempting to connect to SAS %s", _sas_address.c_str());

  if ((_sock = ::socket(AF_INET, SOCK_STREAM, 0)) == -1)
  {
    LOG_ERROR("Failed to open SAS socket: %d (%s)\n", errno, ::strerror(errno));
    return false;
  }

  memset(&addr, 0, sizeof(addr));
  addr.sin_family = AF_INET;
  addr.sin_port = htons(SAS_PORT);
  addr.sin_addr.s_addr = inet_addr(_sas_address.c_str());

  rc = ::connect(_sock, (struct sockaddr*)&addr, sizeof(addr));

  if (rc != 0)
  {
    LOG_ERROR("Failed to connect to SAS %s:%d : %d %s\n", _sas_address.c_str(), SAS_PORT, errno, ::strerror(errno));
    ::close(_sock);
    return false;
  }

  LOG_DEBUG("Connected SAS socket to %s:%d", _sas_address.c_str(), SAS_PORT);

  // Send an init message to SAS.
  std::string init;
  std::string version("v0.1");
  int init_len = INIT_HDR_SIZE + sizeof(uint8_t) + _system_name.length() + sizeof(uint32_t) + sizeof(uint8_t) + version.length();
  init.reserve(init_len);
  write_hdr(init, init_len, SAS_MSG_INIT);
  write_int8(init, (uint8_t)_system_name.length());
  write_data(init, _system_name.length(), _system_name.data());
  int endianness = 1;
  init.append((char*)&endianness, sizeof(int));     // Endianness must be written in machine order.
  write_int8(init, version.length());
  write_data(init, version.length(), version.data());

  LOG_DEBUG("Sending SAS INIT message");

  rc = ::send(_sock, init.data(), init.length(), 0);
  if (rc < 0)
  {
    LOG_ERROR("SAS connection to %s:%d failed: %d %s", _sas_address.c_str(), SAS_PORT, errno, ::strerror(errno));
    return false;
  }

  LOG_STATUS("Connected to SAS %s:%d", _sas_address.c_str(), SAS_PORT);

  return true;
}
예제 #4
0
BgcfService::BgcfService(std::string configuration)
{
  Json::Value root;
  Json::Reader reader;

  std::string jsonData;
  std::ifstream file;

  LOG_STATUS("Loading BGCF configuration from %s", configuration.c_str());

  file.open(configuration.c_str());
  if (file.is_open())
  {
    if (!reader.parse(file, root))
    {
      LOG_WARNING("Failed to read BGCF configuration data, %s",
                  reader.getFormattedErrorMessages().c_str());
      return;
    }

    file.close();

    if (root["routes"].isArray())
    {
      Json::Value routes = root["routes"];

      for (size_t ii = 0; ii < routes.size(); ++ii)
      {
        Json::Value route = routes[(int)ii];
        if ((route["domain"].isString()) &&
            (route["route"].isString()))
        {
          std::string domain = route["domain"].asString();
          std::string via = route["route"].asString();
          _routes.insert(std::make_pair(domain, via));
          LOG_STATUS("Added route to %s via %s", domain.c_str(), via.c_str());
        }
        else
        {
          LOG_WARNING("Badly formed BGCF route entry %s", route.toStyledString().c_str());
        }
      }
    }
    else
    {
      LOG_WARNING("Badly formed BGCF configuration file - missing routes object");
    }
  }
  else
  {
    LOG_WARNING("Failed to read BGCF configuration data %d", file.rdstate());
  }

}
예제 #5
0
void MemcachedStore::update_view()
{
  // Read the memstore file.
  std::ifstream f(_config_file);
  std::vector<std::string> servers;
  std::vector<std::string> new_servers;

  if (f.is_open())
  {
    LOG_STATUS("Reloading memcached configuration from %s file", _config_file.c_str());
    while (f.good())
    {
      std::string line;
      getline(f, line);

      if (line.length() > 0)
      {
        // Read a non-blank line.
        std::vector<std::string> tokens;
        Utils::split_string(line, '=', tokens, 0, true);
        if (tokens.size() != 2)
        {
          LOG_ERROR("Malformed %s file", _config_file.c_str());
          break;
        }

        LOG_STATUS(" %s=%s", tokens[0].c_str(), tokens[1].c_str());

        if (tokens[0] == "servers")
        {
          // Found line defining servers.
          Utils::split_string(tokens[1], ',', servers, 0, true);
        }
        else if (tokens[0] == "new_servers")
        {
          // Found line defining new servers.
          Utils::split_string(tokens[1], ',', new_servers, 0, true);
        }
      }
    }
    f.close();

    if (servers.size() > 0)
    {
      LOG_DEBUG("Update memcached store");
      this->new_view(servers, new_servers);
    }
  }
  else
  {
    LOG_ERROR("Failed to open %s file", _config_file.c_str());
  }
}
예제 #6
0
void VerbApplyEnhancement::onExecute()
{
	NounShip * pShip = WidgetCast<NounShip>( target() );
	if ( context()->isServer() && validate(pShip) && validate(m_pCargo) )
	{
		NounEnhancement::Ref pEnhancement = m_pCargo->enhancement();
		if ( pEnhancement && pEnhancement->parent() == NULL && pEnhancement->canUse( pShip ) )
		{
			// this will attach the contained enhancement to the ship...
			if ( pEnhancement->use( pShip ) )
			{
				// detach the cargo item now..
				pShip->detachNode( m_pCargo );

				pShip->privateChat( CharString().format( "<color;ffffff>Enhancement: Using <color;%6.6x>%s</color> on %s.", 
					pEnhancement->color().RGB(),pEnhancement->getName(), pShip->name() ) );
				LOG_STATUS( "VerbApplyEnhancement", "[ENHANCEMENT]:Apply:%u:%s:%s", 
					pShip->userId(), pEnhancement->getName(),pShip->name() );

				// save off storage with this "active" ship
				context()->user()->saveStorage(pShip);
			}
			else
			{
				pShip->privateChat( CharString().format( "<color;ffffff>Enhancement: Failed to use enhancement <color;%6.6x>%s</color>.",
					pEnhancement->color().RGB(), pEnhancement->getName() ) );
			}
		}
	}
}
예제 #7
0
void ProcessServer::onConnect( dword client )
{
	LOG_STATUS( "ProcessServer", CharString().format("Connecting client %u from %s", client, clientAddress( client )) );

	AutoLock lock( &m_Lock );
	m_ClientValid[ client ] = false;
}
예제 #8
0
void LogClient::onDisconnect()
{
	LOG_STATUS( "LogClient", CharString().format( "LogClient disconnected from %s:%d", (const char *)m_sAddress, m_nPort) );

	m_bLoggedIn = false;
	m_bConnected = false;
	m_nLogLevel = LL_STATUS;
}
예제 #9
0
void HttpStack::wait_stopped()
{
  LOG_STATUS("Waiting for HTTP stack to stop");
  pthread_join(_event_base_thread, NULL);
  evhtp_free(_evhtp);
  _evhtp = NULL;
  event_base_free(_evbase);
  _evbase = NULL;
}
예제 #10
0
void HttpStack::configure(const std::string& bind_address,
                          unsigned short bind_port,
                          int num_threads,
                          AccessLogger* access_logger,
                          LoadMonitor* load_monitor,
                          HttpStack::StatsInterface* stats)
{
  LOG_STATUS("Configuring HTTP stack");
  LOG_STATUS("  Bind address: %s", bind_address.c_str());
  LOG_STATUS("  Bind port:    %u", bind_port);
  LOG_STATUS("  Num threads:  %d", num_threads);
  _bind_address = bind_address;
  _bind_port = bind_port;
  _num_threads = num_threads;
  _access_logger = access_logger;
  _load_monitor = load_monitor;
  _stats = stats;
}
예제 #11
0
bool ProcessServer::validateClient( dword client )
{
	AutoLock lock( &m_Lock );
	Hash<dword,bool>::Iterator find = m_ClientValid.find( client );
	if ( find.valid() && *find )
		return true;

	LOG_STATUS( "ProcessServer", CharString().format("Failed validation, client = %d (%s)", client, clientAddress(client)) );
	removeClient( client );

	return false;
}
예제 #12
0
HttpResolver::HttpResolver(DnsCachedResolver* dns_client,
                           int address_family) :
  BaseResolver(dns_client),
  _address_family(address_family)
{
  LOG_DEBUG("Creating HTTP resolver");

  // Create the blacklist.
  create_blacklist();

  LOG_STATUS("Created HTTP resolver");
}
예제 #13
0
void ProcessServer::onDisconnect( dword client )
{
	AutoLock lock( &m_Lock );

	LOG_STATUS( "ProcessServer", CharString().format("Disconnecting client %u", client) );

	// remove client from hash table
	m_ClientValid.remove( client );

	// remove any open log files
	Array< dword > & logs = m_ClientLog[ client ];
	for(int i=0;i<logs.size();i++)
	{
		dword logId = logs[ i ];

		LOG_STATUS( "ProcessServer", CharString().format("Close Log, logId = %u, client = %u", logId, client) );

		m_ActiveLog.removeSearch( logId );
		m_LogClient.remove( logId );
		m_LogFile.remove( logId );
	}
	m_ClientLog.remove( client );
}
예제 #14
0
void multiQueryUpdate(DISPATCH_PTR dispatch, int32 logStatus)
{
  --MULTI_QUERY_NUM(dispatch);
  --MULTI_QUERY_MAX(dispatch);
  if (MULTI_QUERY_MAX(dispatch) == 0) {
    sendMultiQueryTermination(dispatch);
  } else if (logStatus && MULTI_QUERY_MAX(dispatch) < 0) {
    LOG_STATUS("    MultiQuery: Max replies already received; this reply not actually sent\n");
  }
  if (MULTI_QUERY_NUM(dispatch) == 0) {
    /* Free the class data, saved in "blockCom" slot */
    x_ipcFree((char *)dispatch->blockCom);
  }
}
예제 #15
0
pj_status_t start_transports(int port, pj_str_t& host, pjsip_tpfactory** tcp_factory)
{
  pj_status_t status;

  status = create_udp_transport(port, host);

  if (status != PJ_SUCCESS) {
    return status;
  }

  status = create_tcp_listener_transport(port, host, tcp_factory);

  if (status != PJ_SUCCESS) {
    return status;
  }

  LOG_STATUS("Listening on port %d", port);

  return PJ_SUCCESS;
}
예제 #16
0
void SerialPort::begin_serial(const char* &uart_name, const int &baudrate) {
	// display status as needed
	LOG_DEBUG("Trying to connect to %s.. ", uart_name);
	fflush(stdout);

	// attempt to open the com port
	open_port(uart_name);

	// check for success, display comments as needed
	if (fd == -1) {
		LOG_DEBUG("failure, could not open port.");
		throw EXIT_FAILURE;
	} else {
		LOG_DEBUG("success.\n");
	}

	// display status as needed
	LOG_DEBUG("Trying to configure %s.. ", uart_name);

	// attempt to setup the com port
	bool setup = setup_port(baudrate, 8, 1, false, false);

	// check success, display comments as needed
	if (!setup) {
		LOG_DEBUG("failure, could not configure port.");
		throw EXIT_FAILURE;
	} else {
		LOG_DEBUG("success.\n");
	}

	// error checking, display comments as needed
	if (fd <= 0) {
		LOG_ERROR("Connection attempt to port %s with %d baud, 8N1 failed, exiting.", uart_name, baudrate);
		throw EXIT_FAILURE;
	} else {
		LOG_STATUS("\nConnected to %s with %d baud, 8 data bits, no parity, 1 stop bit (8N1)", uart_name, baudrate);
	}

	// final status update to display as needed
	LOG_DEBUG("\nREADY, waiting for heartbeat.\n");
}
예제 #17
0
DnsCachedResolver::DnsCachedResolver(const std::string& dns_server) :
  _cache_lock(PTHREAD_MUTEX_INITIALIZER),
  _cache()
{
  LOG_STATUS("Creating Cached Resolver using server %s", dns_server.c_str());

  // Initialize the ares library.  This might have already been done by curl
  // but it's safe to do it twice.
  ares_library_init(ARES_LIB_INIT_ALL);

  // Parse the DNS server's IP address.
  if (!inet_aton(dns_server.c_str(), &_dns_server))
  {
    LOG_ERROR("Failed to parse '%s' as IP address - defaulting to 127.0.0.1", dns_server.c_str());
    (void)inet_aton("127.0.0.1", &_dns_server);
  }

  // We store a DNSResolver in thread-local data, so create the thread-local
  // store.
  pthread_key_create(&_thread_local, (void(*)(void*))&destroy_dns_channel);
}
예제 #18
0
파일: stack.cpp 프로젝트: gangbanlau/sprout
pj_status_t create_listener_transports(int port, pjsip_tpfactory** tcp_factory)
{
  pj_status_t status;
  pj_sockaddr_in addr;
  pjsip_host_port published_name;

  addr.sin_family = pj_AF_INET();
  addr.sin_addr.s_addr = 0;
  addr.sin_port = pj_htons((pj_uint16_t)port);

  published_name.host = stack_data.local_host;
  published_name.port = port;

  status = pjsip_udp_transport_start(stack_data.endpt,
                                     &addr,
                                     &published_name,
                                     50,
                                     NULL);
  if (status != PJ_SUCCESS)
  {
    LOG_ERROR("Failed to start UDP transport for port %d (%s)", port, PJUtils::pj_status_to_string(status).c_str());
    return status;
  }

  status = pjsip_tcp_transport_start2(stack_data.endpt,
                                      &addr,
                                      &published_name,
                                      50,
                                      tcp_factory);
  if (status != PJ_SUCCESS)
  {
    LOG_ERROR("Failed to start TCP transport for port %d (%s)", port, PJUtils::pj_status_to_string(status).c_str());
    return status;
  }

  LOG_STATUS("Listening on port %d", port);

  return PJ_SUCCESS;
}
예제 #19
0
void LogClient::onReceive( byte message, const InStream & input )
{
	switch( message )
	{
	case CLIENT_LOGIN:
		{
			unsigned int nLogLevel;
			input >> nLogLevel;

			TRACE( "CLIENT_LOGIN" );

			lock();

			LOG_STATUS( "LogClient", 
				CharString().format( "LogClient connected to %s:%d", (const char *)m_sAddress, m_nPort) );

			m_nLogLevel = nLogLevel;
			m_bLoggedIn = true;

			unlock();
		}
		break;
	}
}
예제 #20
0
void destroy_tcp_listener_transport(int port, pjsip_tpfactory *tcp_factory)
{
  LOG_STATUS("Destroyed TCP transport for port %d", port);
  tcp_factory->destroy(tcp_factory);
}
예제 #21
0
pj_status_t init_stack(const std::string& system_name,
                       const std::string& sas_address,
                       int pcscf_trusted_port,
                       int pcscf_untrusted_port,
                       int scscf_port,
                       int icscf_port,
                       const std::string& local_host,
                       const std::string& public_host,
                       const std::string& home_domain,
                       const std::string& additional_home_domains,
                       const std::string& scscf_uri,
                       const std::string& alias_hosts,
                       SIPResolver* sipresolver,
                       int num_pjsip_threads,
                       int num_worker_threads,
                       int record_routing_model,
                       const int default_session_expires,
                       QuiescingManager *quiescing_mgr_arg,
                       LoadMonitor *load_monitor_arg,
                       const std::string& cdf_domain)
{
  pj_status_t status;
  pj_sockaddr pri_addr;
  pj_sockaddr addr_list[16];
  unsigned addr_cnt = PJ_ARRAY_SIZE(addr_list);
  unsigned i;

  // Set up the vectors of threads.  The threads don't get created until
  // start_stack is called.
  pjsip_threads.resize(num_pjsip_threads);
  worker_threads.resize(num_worker_threads);

  // Get ports and host names specified on options.  If local host was not
  // specified, use the host name returned by pj_gethostname.
  char* local_host_cstr = strdup(local_host.c_str());
  char* public_host_cstr = strdup(public_host.c_str());
  char* home_domain_cstr = strdup(home_domain.c_str());
  char* scscf_uri_cstr;
  if (scscf_uri.empty())
  {
    // Create a default S-CSCF URI using the localhost and S-CSCF port.
    std::string tmp_scscf_uri = "sip:" + local_host + ":" + std::to_string(scscf_port) + ";transport=TCP";
    scscf_uri_cstr = strdup(tmp_scscf_uri.c_str());
  }
  else
  {
    // Use the specified URI.
    scscf_uri_cstr = strdup(scscf_uri.c_str());
  }

  // This is only set on Bono nodes (it's the empty string otherwise)
  char* cdf_domain_cstr = strdup(cdf_domain.c_str());

  // Copy port numbers to stack data.
  stack_data.pcscf_trusted_port = pcscf_trusted_port;
  stack_data.pcscf_untrusted_port = pcscf_untrusted_port;
  stack_data.scscf_port = scscf_port;
  stack_data.icscf_port = icscf_port;

  stack_data.sipresolver = sipresolver;

  // Copy other functional options to stack data.
  stack_data.default_session_expires = default_session_expires;

  // Work out local and public hostnames and cluster domain names.
  stack_data.local_host = (local_host != "") ? pj_str(local_host_cstr) : *pj_gethostname();
  stack_data.public_host = (public_host != "") ? pj_str(public_host_cstr) : stack_data.local_host;
  stack_data.default_home_domain = (home_domain != "") ? pj_str(home_domain_cstr) : stack_data.local_host;
  stack_data.scscf_uri = pj_str(scscf_uri_cstr);
  stack_data.cdf_domain = pj_str(cdf_domain_cstr);

  // Build a set of home domains
  stack_data.home_domains = std::unordered_set<std::string>();
  stack_data.home_domains.insert(PJUtils::pj_str_to_string(&stack_data.default_home_domain));
  if (additional_home_domains != "")
  {
    std::list<std::string> domains;
    Utils::split_string(additional_home_domains, ',', domains, 0, true);
    stack_data.home_domains.insert(domains.begin(), domains.end());
  }

  // Set up the default address family.  This is IPv4 unless our local host is an IPv6 address.
  stack_data.addr_family = AF_INET;
  struct in6_addr dummy_addr;
  if (inet_pton(AF_INET6, local_host_cstr, &dummy_addr) == 1)
  {
    LOG_DEBUG("Local host is an IPv6 address - enabling IPv6 mode");
    stack_data.addr_family = AF_INET6;
  }

  stack_data.record_route_on_every_hop = false;
  stack_data.record_route_on_initiation_of_originating = false;
  stack_data.record_route_on_initiation_of_terminating = false;
  stack_data.record_route_on_completion_of_originating = false;
  stack_data.record_route_on_completion_of_terminating = false;
  stack_data.record_route_on_diversion = false;

  if (scscf_port != 0)
  {
    switch (record_routing_model)
    {
    case 1:
      stack_data.record_route_on_initiation_of_originating = true;
      stack_data.record_route_on_completion_of_terminating = true;
      break;
    case 2:
      stack_data.record_route_on_initiation_of_originating = true;
      stack_data.record_route_on_initiation_of_terminating = true;
      stack_data.record_route_on_completion_of_originating = true;
      stack_data.record_route_on_completion_of_terminating = true;
      stack_data.record_route_on_diversion = true;
      break;
    case 3:
      stack_data.record_route_on_every_hop = true;
      stack_data.record_route_on_initiation_of_originating = true;
      stack_data.record_route_on_initiation_of_terminating = true;
      stack_data.record_route_on_completion_of_originating = true;
      stack_data.record_route_on_completion_of_terminating = true;
      stack_data.record_route_on_diversion = true;
      break;
    default:
      LOG_ERROR("Record-Route setting should be 1, 2, or 3, is %d. Defaulting to Record-Route on every hop.", record_routing_model);
      stack_data.record_route_on_every_hop = true;
    }
  }

  std::string system_name_sas = system_name;
  std::string system_type_sas = (pcscf_trusted_port != 0) ? "bono" : "sprout";
  // Initialize SAS logging.
  if (system_name_sas == "")
  {
    system_name_sas = std::string(stack_data.local_host.ptr, stack_data.local_host.slen);
  }
  SAS::init(system_name,
            system_type_sas,
            SASEvent::CURRENT_RESOURCE_BUNDLE,
            sas_address,
            sas_write);

  // Initialise PJSIP and all the associated resources.
  status = init_pjsip();

  // Register the stack module.
  pjsip_endpt_register_module(stack_data.endpt, &mod_stack);
  stack_data.module_id = mod_stack.id;

  // Initialize the PJUtils module.
  PJUtils::init();

  // Create listening transports for the ports whichtrusted and untrusted ports.
  stack_data.pcscf_trusted_tcp_factory = NULL;
  if (stack_data.pcscf_trusted_port != 0)
  {
    status = start_transports(stack_data.pcscf_trusted_port,
                              stack_data.local_host,
                              &stack_data.pcscf_trusted_tcp_factory);
    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
  }

  stack_data.pcscf_untrusted_tcp_factory = NULL;
  if (stack_data.pcscf_untrusted_port != 0)
  {
    status = start_transports(stack_data.pcscf_untrusted_port,
                              stack_data.public_host,
                              &stack_data.pcscf_untrusted_tcp_factory);
    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
  }

  stack_data.scscf_tcp_factory = NULL;
  if (stack_data.scscf_port != 0)
  {
    status = start_transports(stack_data.scscf_port,
                              stack_data.public_host,
                              &stack_data.scscf_tcp_factory);
    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
  }

  stack_data.icscf_tcp_factory = NULL;
  if (stack_data.icscf_port != 0)
  {
    status = start_transports(stack_data.icscf_port,
                              stack_data.public_host,
                              &stack_data.icscf_tcp_factory);
    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
  }

  // List all names matching local endpoint.
  // Note that PJLIB version 0.6 and newer has a function to
  // enumerate local IP interface (pj_enum_ip_interface()), so
  // by using it would be possible to list all IP interfaces in
  // this host.

  // The first address is important since this would be the one
  // to be added in Record-Route.
  stack_data.name[stack_data.name_cnt] = stack_data.local_host;
  stack_data.name_cnt++;

  if (strcmp(local_host_cstr, public_host_cstr))
  {
    stack_data.name[stack_data.name_cnt] = stack_data.public_host;
    stack_data.name_cnt++;
  }

  if ((scscf_port != 0) &&
      (!scscf_uri.empty()))
  {
    // S-CSCF enabled with a specified URI, so add host name from the URI to hostnames.
    pjsip_sip_uri* uri = (pjsip_sip_uri*)PJUtils::uri_from_string(scscf_uri,
                                                                  stack_data.pool);
    if (uri != NULL)
    {
      stack_data.name[stack_data.name_cnt] = uri->host;
      stack_data.name_cnt++;
    }
  }

  if (pj_gethostip(pj_AF_INET(), &pri_addr) == PJ_SUCCESS)
  {
    pj_strdup2(stack_data.pool, &stack_data.name[stack_data.name_cnt],
               pj_inet_ntoa(pri_addr.ipv4.sin_addr));
    stack_data.name_cnt++;
  }

  // Get the rest of IP interfaces.
  if (pj_enum_ip_interface(pj_AF_INET(), &addr_cnt, addr_list) == PJ_SUCCESS)
  {
    for (i = 0; i < addr_cnt; ++i)
    {
      if (addr_list[i].ipv4.sin_addr.s_addr == pri_addr.ipv4.sin_addr.s_addr)
      {
        continue;
      }

      pj_strdup2(stack_data.pool, &stack_data.name[stack_data.name_cnt],
                 pj_inet_ntoa(addr_list[i].ipv4.sin_addr));
      stack_data.name_cnt++;
    }
  }

  // Note that we no longer consider 127.0.0.1 and localhost as aliases.

  // Parse the list of alias host names.
  stack_data.aliases = std::unordered_set<std::string>();
  if (alias_hosts != "")
  {
    std::list<std::string> aliases;
    Utils::split_string(alias_hosts, ',', aliases, 0, true);
    stack_data.aliases.insert(aliases.begin(), aliases.end());
    for (std::unordered_set<std::string>::iterator it = stack_data.aliases.begin();
         it != stack_data.aliases.end();
         ++it)
    {
      pj_strdup2(stack_data.pool, &stack_data.name[stack_data.name_cnt], it->c_str());
      stack_data.name_cnt++;
    }
  }

  LOG_STATUS("Local host aliases:");
  for (i = 0; i < stack_data.name_cnt; ++i)
  {
    LOG_STATUS(" %.*s",
               (int)stack_data.name[i].slen,
               stack_data.name[i].ptr);
  }

  // Set up the Last Value Cache, accumulators and counters.
  std::string zmq_port = SPROUT_ZMQ_PORT;

  if ((stack_data.pcscf_trusted_port != 0) &&
      (stack_data.pcscf_untrusted_port != 0))
  {
    zmq_port = BONO_ZMQ_PORT;
  }

  stack_data.stats_aggregator = new LastValueCache(num_known_stats,
                                                   known_statnames,
                                                   zmq_port);

  latency_accumulator = new StatisticAccumulator("latency_us",
                                                 stack_data.stats_aggregator);
  queue_size_accumulator = new StatisticAccumulator("queue_size",
                                                    stack_data.stats_aggregator);
  requests_counter = new StatisticCounter("incoming_requests",
                                          stack_data.stats_aggregator);
  overload_counter = new StatisticCounter("rejected_overload",
                                          stack_data.stats_aggregator);

  if (load_monitor_arg != NULL)
  {
    load_monitor = load_monitor_arg;
  }

  if (quiescing_mgr_arg != NULL)
  {
    quiescing_mgr = quiescing_mgr_arg;

    // Create an instance of the stack quiesce handler. This acts as a glue
    // class between the stack modulem connections tracker, and the quiescing
    // manager.
    stack_quiesce_handler = new StackQuiesceHandler();

    // Create a new connection tracker, and register the quiesce handler with
    // it.
    connection_tracker = new ConnectionTracker(stack_quiesce_handler);

    // Register the quiesce handler with the quiescing manager (the former
    // implements the connection handling interface).
    quiescing_mgr->register_conns_handler(stack_quiesce_handler);
  }

  return status;
}
예제 #22
0
파일: stack.cpp 프로젝트: gangbanlau/sprout
pj_status_t init_stack(const std::string& system_name,
                       const std::string& sas_address,
                       int trusted_port,
                       int untrusted_port,
                       const std::string& local_host,
                       const std::string& home_domain,
                       const std::string& sprout_cluster_domain,
                       const std::string& alias_hosts,
                       int num_pjsip_threads,
                       int num_worker_threads)
{
  pj_status_t status;
  pj_sockaddr pri_addr;
  pj_sockaddr addr_list[16];
  unsigned addr_cnt = PJ_ARRAY_SIZE(addr_list);
  unsigned i;

  // Set up the vectors of threads.  The threads don't get created until
  // start_stack is called.
  pjsip_threads.resize(num_pjsip_threads);
  worker_threads.resize(num_worker_threads);

  // Get ports and host names specified on options.  If local host was not
  // specified, use the host name returned by pj_gethostname.
  memset(&stack_data, 0, sizeof(stack_data));
  char* local_host_cstr = strdup(local_host.c_str());
  char* home_domain_cstr = strdup(home_domain.c_str());
  char* sprout_cluster_domain_cstr = strdup(sprout_cluster_domain.c_str());
  stack_data.trusted_port = trusted_port;
  stack_data.untrusted_port = untrusted_port;
  stack_data.local_host = (local_host != "") ? pj_str(local_host_cstr) : *pj_gethostname();
  stack_data.home_domain = (home_domain != "") ? pj_str(home_domain_cstr) : stack_data.local_host;
  stack_data.sprout_cluster_domain = (sprout_cluster_domain != "") ? pj_str(sprout_cluster_domain_cstr) : stack_data.local_host;

  // Initialize SAS logging.
  if (system_name != "")
  {
    SAS::init(system_name.length(), system_name.c_str(), sas_address);
  }
  else
  {
    SAS::init(stack_data.local_host.slen, stack_data.local_host.ptr, sas_address);
  }

  // Initialise PJSIP and all the associated resources.
  status = init_pjsip();

  // Register the stack module.
  pjsip_endpt_register_module(stack_data.endpt, &mod_stack);
  stack_data.module_id = mod_stack.id;

  // Create listening transports for trusted and untrusted ports.
  if (stack_data.trusted_port != 0)
  {
    status = create_listener_transports(stack_data.trusted_port, &stack_data.tcp_factory);
    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
  }
  if (stack_data.untrusted_port != 0)
  {
    status = create_listener_transports(stack_data.untrusted_port, NULL);
    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
  }

  // List all names matching local endpoint.
  // Note that PJLIB version 0.6 and newer has a function to
  // enumerate local IP interface (pj_enum_ip_interface()), so
  // by using it would be possible to list all IP interfaces in
  // this host.

  // The first address is important since this would be the one
  // to be added in Record-Route.
  stack_data.name[stack_data.name_cnt] = stack_data.local_host;
  stack_data.name_cnt++;

  if (pj_gethostip(pj_AF_INET(), &pri_addr) == PJ_SUCCESS)
  {
    pj_strdup2(stack_data.pool, &stack_data.name[stack_data.name_cnt],
               pj_inet_ntoa(pri_addr.ipv4.sin_addr));
    stack_data.name_cnt++;
  }

  // Get the rest of IP interfaces.
  if (pj_enum_ip_interface(pj_AF_INET(), &addr_cnt, addr_list) == PJ_SUCCESS)
  {
    for (i = 0; i < addr_cnt; ++i)
    {
      if (addr_list[i].ipv4.sin_addr.s_addr == pri_addr.ipv4.sin_addr.s_addr)
      {
        continue;
      }

      pj_strdup2(stack_data.pool, &stack_data.name[stack_data.name_cnt],
                 pj_inet_ntoa(addr_list[i].ipv4.sin_addr));
      stack_data.name_cnt++;
    }
  }

  // Add loopback address.
#if PJ_IP_HELPER_IGNORE_LOOPBACK_IF
  stack_data.name[stack_data.name_cnt] = pj_str("127.0.0.1");
  stack_data.name_cnt++;
#endif

  stack_data.name[stack_data.name_cnt] = pj_str("localhost");
  stack_data.name_cnt++;
  // Parse the list of alias host names.
  if (alias_hosts != "")
  {
    std::list<std::string> hosts;
    Utils::split_string(alias_hosts, ',', hosts, 0, true);
    for (std::list<std::string>::iterator it = hosts.begin();
         it != hosts.end();
         ++it)
    {
      pj_strdup2(stack_data.pool, &stack_data.name[stack_data.name_cnt], it->c_str());
      stack_data.name_cnt++;
    }
  }

  LOG_STATUS("Local host aliases:");
  for (i = 0; i < stack_data.name_cnt; ++i)
  {
    LOG_STATUS(" %.*s",
               (int)stack_data.name[i].slen,
               stack_data.name[i].ptr);
  }

  stack_data.stats_aggregator = new LastValueCache(Statistic::known_stats_count(),
                                                   Statistic::known_stats());

  latency_accumulator = new StatisticAccumulator("latency_us");

  return status;
}
예제 #23
0
int main( int argc, char ** argv )
{
	CharString iniFile = "./ProcessServer.ini";
	if ( argc > 1 )
		iniFile = argv[1];

	Settings settings( "ProcessServer", iniFile );
	
	// initialize the logging first thing before we do anything else..
	std::string logFile( settings.get( "logFile", "ProcessServer.log" ) );
	std::string logExclude( settings.get( "logExclude", "" ) );
	unsigned int nMinLogLevel = settings.get( "logLevel", LL_STATUS );
	new FileReactor( logFile, nMinLogLevel, logExclude );

	bool bRemoteUpdate = settings.get( "remoteUpdate", 1 ) != 0;
	bool bLocalUpdate = settings.get( "localUpdate", (dword)0 ) != 0;

	CharString sPath( FileDisk::currentDirectory() );
	if (! sPath.endsWith( PATH_SEPERATOR ) )
		sPath += PATH_SEPERATOR;

#if !defined(_DEBUG)
	// update the files
	if ( settings.get( "doUpdate", 1 ) != 0 )
	{
		settings.put( "doUpdate", (dword)0 );

		if ( bLocalUpdate )
		{
			CharString updatePath = settings.get( "localUpdatePath", "" );
			if ( updatePath.length() > 0 )
			{
				FileDisk::normalizePath( updatePath.buffer() );
				if (! updatePath.endsWith( PATH_SEPERATOR ) )
					updatePath += PATH_SEPERATOR;

				// copy the files from a directory
				if ( localUpdate( sPath, updatePath ) )
					return -3;		// let the service/script update our files..
			}
		}
	}
#endif

	// do the update next time!
	settings.put( "doUpdate", 1 );

	ProcessServer::Context context;
	context.logFile = logFile.c_str();
	context.name = settings.get( "name", "ProcessServer" );
	context.config = iniFile;
	context.gameId = settings.get( "gameId", 1 );
	context.processGroup = settings.get( "processGroup", 1 );
	context.networkGroup = settings.get( "networkGroup", 1 );
	context.metaAddress = settings.get( "metaAddress", "meta-server.palestar.com" );
	context.metaPort = settings.get( "metaPort", 9000 );
	context.uid = settings.get( "uid", "DSS" );
	context.pw = settings.get( "pw", "darkspace" );
	context.address = settings.get( "address", "" );
	context.port = settings.get( "port", 8000 );
	context.maxClients = settings.get( "maxClients", 1000 );
	context.processFile = iniFile;
	context.syncClock = settings.get ("syncClock", (dword)0 ) != 0;

	// start the server
	MyProcessServer theServer;
	if (! theServer.start( context ) )
		return -1;

	// signal that we are running
	Event serverRunning( "ProcessServerRun" );
	serverRunning.signal();

	dword nNextUpdateCheck = Time::seconds() + settings.get("updateTime",300);
	dword nLastCRC = 0;

	// run the server forever, unless it crashes
	Event serverStop( "ProcessServerStop" );
	while( theServer.running() && !theServer.shutdownCompleted() )
	{
		if (! serverStop.wait( 10 ) )
		{
			LOG_STATUS( "ProcessServer", "Recevied shutdown signal." );
			theServer.shutdown();

			serverStop.clear();
		}

		theServer.update();
		theServer.updatePerformanceMonitor();

#if !defined(_DEBUG)
		if ( bRemoteUpdate && nNextUpdateCheck < Time::seconds() )
		{
			// check for new code update
			MirrorClient mirrorClient;
			if ( mirrorClient.open( 
				settings.get( "mirrorAddress", "mirror-server.palestar.com" ),
				settings.get( "mirrorPort", 9200 ), sPath, NULL, true ) )
			{
				// attempt to login, ingore if failed
				mirrorClient.login( settings.get( "uid", "" ), settings.get( "pw", "" ) );

				// get the CRC only, only do a sync if remote files have been changed...
				dword nCRC = mirrorClient.getCRC();
				if ( nCRC != nLastCRC )
				{
					nLastCRC = nCRC;

					dword nJobID = mirrorClient.syncronize();
					if ( nJobID != 0 && mirrorClient.waitJob( nJobID, 86400 * 1000 ) )
					{
						int nWarningTime = settings.get( "warningTime", 300 );

						LOG_STATUS( "ProcessServer", "Files updated -- Restarting the server in %d seconds.", nWarningTime );

						CharString sWarningMessage = settings.get( "warningMessage", 
							CharString().format("/notice /%s Updating in $T...", context.name.cstr() ) );
						while( nWarningTime > 0 )
						{
							CharString sTimeLeft;
							sTimeLeft.format("%d %s", 
								nWarningTime > 60 ? nWarningTime / 60 : nWarningTime,
								nWarningTime > 60 ? "minute(s)" : "second(s)");

							// replace the "$T" token with the time remaining...
							CharString sChat = sWarningMessage;
							sChat.replace( "$T", sTimeLeft );

							theServer.sendChat( sChat );

							int nSleepTime = 0;
							if ( nWarningTime > (60 * 10) )
								nSleepTime = 60 * 5;			// sleep for 5 minutes
							else
								nSleepTime = 60;				// sleep for 1 minute

							if ( nSleepTime > nWarningTime )
								nSleepTime = nWarningTime;

							nWarningTime -= nSleepTime;

							dword nEndSleep = Time::seconds() + nSleepTime;
							while( Time::seconds() < nEndSleep )
							{
								if (! serverStop.wait( 10 ) )
								{
									LOG_STATUS( "ProcessServer", "Received stop signal, stopping now." );
									nSleepTime = nWarningTime = 0;		// stop now... no warning
									break;
								}

								theServer.update();
								theServer.updatePerformanceMonitor();
							}
						}

						// start the shutdown, server will exit once the last process has stopped..
						theServer.shutdown();
					}
				}
				mirrorClient.close();
			}
			else
			{
				LOG_ERROR( "ProcessServer", "Failed to connect to MirrorServer!" );
			}
		

			nNextUpdateCheck = Time::seconds() + settings.get("updateTime",300);
		}
#endif
	}

	theServer.stop();

	return 0;
}
예제 #24
0
	void sendChat( const char * pChat )
	{
		LOG_STATUS( "ProcessServer", "Sending Chat: %s", pChat );
		m_MetaClient.sendChat( 0, pChat );
	}
예제 #25
0
void HttpStack::stop()
{
  LOG_STATUS("Stopping HTTP stack");
  event_base_loopbreak(_evbase);
  evhtp_unbind_socket(_evhtp);
}
예제 #26
0
파일: bgcfservice.cpp 프로젝트: jmmL/sprout
void BgcfService::update_routes()
{
  Json::Value root;
  Json::Reader reader;

  std::string jsonData;
  std::ifstream file;

  LOG_STATUS("Loading BGCF configuration from %s", _configuration.c_str());

  std::map<std::string, std::vector<std::string>> new_routes;

  file.open(_configuration.c_str());
  if (file.is_open())
  {
    if (!reader.parse(file, root))
    {
      LOG_WARNING("Failed to read BGCF configuration data, %s",
                  reader.getFormattedErrorMessages().c_str());
      return;
    }

    file.close();

    if (root["routes"].isArray())
    {
      Json::Value routes = root["routes"];

      for (size_t ii = 0; ii < routes.size(); ++ii)
      {
        Json::Value route = routes[(int)ii];
        if ((route["domain"].isString()) &&
            (route["route"].isArray()))
        {
          std::vector<std::string> route_vec;
          Json::Value route_vals = route["route"];
          std::string domain = route["domain"].asString();

          LOG_DEBUG("Add route for %s", domain.c_str());

          for (size_t jj = 0; jj < route_vals.size(); ++jj)
          {
            Json::Value route_val = route_vals[(int)jj];
            std::string route_uri = route_val.asString();
            LOG_DEBUG("  %s", route_uri.c_str());
            route_vec.push_back(route_uri);
          }

          new_routes.insert(std::make_pair(domain, route_vec));
          route_vec.clear();
        }
        else
        {
          LOG_WARNING("Badly formed BGCF route entry %s", route.toStyledString().c_str());
        }
      }

      _routes = new_routes;
    }
    else
    {
      LOG_WARNING("Badly formed BGCF configuration file - missing routes object");
    }
  }
  else
  {
    LOG_WARNING("Failed to read BGCF configuration data %d", file.rdstate());
  }
}
예제 #27
0
void SCSCFSelector::update_scscf()
{
  Json::Value root;
  Json::Reader reader;

  std::string jsonData;
  std::ifstream file;

  std::vector<scscf_t> new_scscfs;

  // Check whether the file exists.
  struct stat s;
  if ((stat(_configuration.c_str(), &s) != 0) &&
      (errno == ENOENT))
  {
    LOG_STATUS("No S-CSCF configuration data (file %s does not exist)",
               _configuration.c_str());
    return;
  }

  // The file exists so try to open it.
  LOG_STATUS("Loading S-CSCF configuration from %s", _configuration.c_str());

  file.open(_configuration.c_str());
  if (file.is_open())
  {
    if (!reader.parse(file, root))
    {
      LOG_WARNING("Failed to read S-CSCF configuration data, %s",
                  reader.getFormattedErrorMessages().c_str());
      return;
    }

    file.close();

    if (root["s-cscfs"].isArray())
    {
      Json::Value scscfs = root["s-cscfs"];

      for (size_t ii = 0; ii < scscfs.size(); ++ii)
      {
        Json::Value scscf = scscfs[(int)ii];

        if ((scscf["server"].isString()) &&
            (scscf["priority"].isInt()) &&
            (scscf["weight"].isInt()) &&
            (scscf["capabilities"].isArray()))
        {
          scscf_t new_scscf;

          new_scscf.server = scscf["server"].asString();
          new_scscf.priority = scscf["priority"].asInt();
          new_scscf.weight = scscf["weight"].asInt();

          Json::Value capabilities_vals = scscf["capabilities"];
          std::vector<int> capabilities_vec;

          for (size_t jj = 0; jj < capabilities_vals.size(); ++jj)
          {
            Json::Value capability_val = capabilities_vals[(int)jj];
            capabilities_vec.push_back(capability_val.asInt());
          }

          // Sort the capabalities and remove duplicates
          std::sort(capabilities_vec.begin(), capabilities_vec.end());
          capabilities_vec.erase(unique(capabilities_vec.begin(), capabilities_vec.end() ), capabilities_vec.end() );
          new_scscf.capabilities = capabilities_vec;
          new_scscfs.push_back(new_scscf);
          capabilities_vec.clear();
        }
        else
        {
          LOG_WARNING("Badly formed S-CSCF entry %s", scscf.toStyledString().c_str());
        }
      }

      _scscfs = new_scscfs;
    }
    else
    {
      LOG_WARNING("Badly formed S-CSCF configuration file - missing s-cscfs object");
    }
  }
  else
  {
    //LCOV_EXCL_START
    LOG_WARNING("Failed to read S-CSCF configuration data %d", file.rdstate());
    //LCOV_EXCL_STOP
  }
}
예제 #28
0
void ProcessServer::updateDemon()
{
	dword lastRegister = 0;
	dword lastTimeSync = 0;
	dword pingTime = 0;

	while ( running() && !m_bShutdownCompleted )
	{
		Thread::sleep( 1000 );

		if (! m_MetaClient.loggedIn() )
		{
			LOG_STATUS( "ProcessServer", "Establishing connection to the metaserver" );

			// attempt to connect
			if ( m_MetaClient.open( m_Context.metaAddress, m_Context.metaPort ) > 0 )
			{
				if ( m_MetaClient.login( m_Context.uid, m_Context.pw ) < 0 )
				{
					LOG_STATUS( "ProcessServer", "Failed to login to the metaserver" );
					m_MetaClient.close();	// failed to login
				}
				else
				{
					LOG_STATUS( "ProcessServer", "Connected to the metaserver" );
					// select the correct game
					m_MetaClient.selectGame( m_Context.gameId );
				}
			}
		}
		
		m_MetaClient.update();
		if ( m_MetaClient.loggedIn() )
		{
			if ( lastRegister < (Time::seconds() - REGISTER_TIME) )
			{
				AutoLock lock( &m_Lock );

				MetaClient::Server server;
				server.gameId = m_Context.gameId;
				server.type = MetaClient::PROCESS_SERVER;
				server.flags = 0;
				server.name = m_Context.name;
				server.shortDescription.format( "CPU: %d%%, MEM: %d%%", cpuUsage(), memoryUsage() );

				server.description = server.shortDescription + "\n\n";
				for(int i=0;i<m_ProcessList.size();i++)
				{
					Process & proc = m_ProcessList[ i ];
					if ( (proc.flags & ProcessClient::PF_RUNNING) == 0 )
						continue;
					server.description += CharString().format( "%s\n", proc.name.cstr() );
				}

				server.address = m_Context.address;
				server.port = m_Context.port;
				server.maxClients = m_Context.maxClients;
				server.clients = clientCount();
				server.data = CharString().format("processGroup=%u;networkGroup=%u;processCount=%u;cpuUsage=%d;memoryUsage=%d", 
					m_Context.processGroup, m_Context.networkGroup, m_ProcessList.size(), cpuUsage(), memoryUsage() );

				lock.release();

				if ( m_MetaClient.registerServer( server ) < 0 )
					lastRegister = (Time::seconds() - REGISTER_TIME) + 30;		// failed, try again in 30 seconds
				else
					lastRegister = Time::seconds();
			}

			if ( m_Context.syncClock && lastTimeSync < (Time::seconds() - SYNC_CLOCKS_TIME) )
			{
				// get the current time from the metaserver
				dword currentTime = m_MetaClient.getTime();
				if ( currentTime > 0 )
				{
					LOG_STATUS( "ProcessServer", "Syncronizing system time to %s", Time::format( currentTime, "%c" ).cstr() );

					if (! Time::setTime( currentTime ) )
						LOG_STATUS( "ProcessServer", "Failed to set the system time!" );

					lastTimeSync = Time::seconds();
				}
				else
				{
					LOG_STATUS( "ProcessServer", "Failed to syncronize system time from MetaServer!" );
					lastTimeSync = (Time::seconds() - SYNC_CLOCKS_TIME) + 300;		// try again in another 5 min
				}
			}
		}

		AutoLock lock( &m_Lock );

		bool shutdownComplete = true;			// have all child processes stopped

		// check for log updates
		for(int i=0;i<m_ActiveLog.size();i++)
		{
			dword logId = m_ActiveLog[ i ];

			FileDisk & file = m_LogFile[ logId ];

			try {
				if ( file.position() > file.size() )
					file.setPosition( 0 );		// file has been rotated... reset read position

				dword read = file.size() - file.position();
				if ( read > 0 )
				{
					if ( read > MAX_LOG_SIZE )
					{
						file.setPosition( file.size() - MAX_LOG_SIZE );
						read = MAX_LOG_SIZE;
					}
				
					char * pLines = new char[ read + 1 ];
					pLines[ read ] = 0;

					file.read( pLines, read );

					send( m_LogClient[ logId ], ProcessClient::CLIENT_RECV_LOG_UPDATE ) << logId << CharString(pLines);

					delete [] pLines;
				}
			}
			catch( FileDisk::FileError )
			{
				LOG_STATUS( "ProcessServer", CharString().format("Log Read Error, logFile = %s, logId = %u", file.fileName(), logId) );

				// close the previously open file
				file.close();
				// attempt to reopen the file
				file.open( file.fileName() );
			}
		}

		// check process list
		for(int i=0;i<m_ProcessList.size();i++)
		{
			Process & proc = m_ProcessList[ i ];
			if ( m_ProcessInfo.find( proc.processId ).valid() )
			{
				ProcessInfo & info = m_ProcessInfo[ proc.processId ];

				proc.flags |= ProcessClient::PF_RUNNING;
				if ( (proc.flags & ProcessClient::PF_DISABLED) == 0 )
				{
					// make sure the process is still running
					if (! ::Process::active( info.m_pHandle ) )
					{
						proc.flags &= ~ProcessClient::PF_RUNNING;

						if ( ! m_Shutdown )
						{
							if ( info.m_nRestartTime != 0 && Time::seconds() < info.m_nRestartTime )
								continue;		// not time to restart yet, continue onto the next process..

							// process has exited, increment the number of restarts, then calculate the next restart
							// time increasing the wait time each time the process exits
							info.m_nRestarts += 1;
							info.m_nRestartTime = Time::seconds() + (60 * (info.m_nRestarts * info.m_nRestarts) );

							int exitCode = ::Process::exitCode( info.m_pHandle );
							::Process::close( info.m_pHandle );

							CharString message;
							message.format( "Process %u exit, name = %s, exec = %s, arg = %s, exitCode = %d, restarts = %u", 
								proc.processId, proc.name.cstr(), proc.executable.cstr(), proc.arguments.cstr(), exitCode, info.m_nRestarts );
							LOG_STATUS( "ProcessServer", message );


							// send report if exit code is negative
							if ( exitCode < 0 )
								m_MetaClient.sendChat( 0, CharString().format("/report %s", message.cstr()) );

							// restart the process..
							Path exePath( proc.executable );
							void * pStart = ::Process::start( CharString().format("%s %s", exePath.file().cstr(), proc.arguments.cstr()), 
								exePath.directory() );
							if ( pStart == NULL )
							{
								LOG_STATUS( "ProcessServer", "Process %u failed to restart", proc.processId );

								m_ProcessInfo.remove( proc.processId );
								proc.flags |= ProcessClient::PF_DISABLED;
							}
							else
							{
								LOG_STATUS( "ProcessServer", "Process %u restarted", proc.processId );
								info.m_pHandle = pStart;
							}
						}
						else
						{
							int exitCode = ::Process::exitCode( info.m_pHandle );

							LOG_STATUS( "ProcessServer", "Process Stopped, name = %s, exitCode = %d", proc.name.cstr(), exitCode );
							::Process::close( info.m_pHandle );

							m_ProcessInfo.remove( proc.processId );
						}
						
					}
					else if ( m_Shutdown )
					{
						shutdownComplete = false;	
						stopProcess( proc.processId );
					}
					else if ( info.m_nRestartTime != 0 && Time::seconds() > info.m_nRestartTime )
					{
						// process has been running long enough to clear the restart time.
						info.m_nRestartTime = 0;
						info.m_nRestarts = 0;
					}
				}
				else
				{
					if (! ::Process::active( info.m_pHandle ) )
					{
						LOG_STATUS( "ProcessServer", "Process Stopped, name = %s", proc.name.cstr() );
						::Process::close( info.m_pHandle );

						m_ProcessInfo.remove( proc.processId );
					}
					else
						stopProcess( proc.processId );
				}
			}
			else
			{
				proc.flags &= ~ProcessClient::PF_RUNNING;
				if ( (proc.flags & ProcessClient::PF_DISABLED) == 0 && !m_Shutdown )
				{
					LOG_STATUS( "ProcessServer", "Starting Process %u, name = %s, exec = %s, arg = %s", 
						proc.processId, proc.name.cstr(), proc.executable.cstr(), proc.arguments.cstr() );

					Path exePath( proc.executable );
					void * pStart = ::Process::start( CharString().format("%s %s", exePath.file().cstr(), proc.arguments.cstr()),
						exePath.directory() );
					if ( pStart == NULL )
					{
						proc.flags |= ProcessClient::PF_DISABLED;

						LOG_STATUS( "ProcessServer", "Process %u Failed to Start, name = %s, exec = %s", 
							proc.processId, proc.name.cstr(), proc.executable.cstr() );
					}
					else
						m_ProcessInfo[ proc.processId ].m_pHandle = pStart;
				}
			}
		}

		pingTime++;
		if ( pingTime > 15 )
		{
			// ping all clients
			for(int i=0;i<clientCount();i++)
				send( client(i), ProcessClient::PING );
			
			pingTime = 0;
		}

		// check for shutdown
		if ( m_Shutdown && shutdownComplete )
		{
			m_bShutdownCompleted = true;

			if ( m_RebootOnShutdown )
				rebootMachine();
		}

		lock.release();
	}
}
예제 #29
0
void NounShip::destroyShip( Noun * pKiller, bool bZeroVelocity )
{
	// make sure the damage is enough
	m_Damage = maxDamage();
	// clear the current order & command, so if they respawn the ship doesn't try to keep doing it's last command
	setCommand( NOCOMMAND, NULL );
	setOrder( NOORDER, NULL, NULL );

	// inform the context user first
	if ( pKiller != this )
	{
		gameContext()->gameUser()->onDestroyed( this, pKiller );
		if ( pKiller != NULL )
			gameContext()->gameUser()->onKill( pKiller, this );
	}
	else 
		gameContext()->gameUser()->onSelfDestruct( this );

	if ( WidgetCast<NounPlanet>( pKiller ) )
		gameContext()->gameUser()->onCollidePlanet( this );

	// create the primary explosion
	if ( context()->isClient() )
	{
		Scene * pScene = destroyEffect();
		if ( pScene != NULL )
		{
			// TODO: no need to add this explosion of this player is nowhere near the explosion
			// ship destroyed, create the explosion effect
			SceneryDebris * pEffect = new SceneryDebris;
			pEffect->setNounContext( new NounContext( pScene ) );
			pEffect->setContext( context() );
			pEffect->setPosition( worldPosition() );
			pEffect->setDelay( 0.0f );
			pEffect->setFrame( frame() );

			if (! bZeroVelocity )
				pEffect->setVelocity( Vector3( sin( m_fHeading ) * m_fVelocity, 0.0f, cos( m_fHeading) * m_fVelocity ) );
			if (! pEffect->setSegment( "Effect" ) )
				pEffect->setLife( 15.0f );

			context()->attachNoun( pEffect );
		}

		NounTrail::CopyTrailsIntoZone( this );
	}

	// list of destroyed items to remove from ship..
	std::list< Noun * > destroyed;

	// damage enhancements, once they reach their maxDamage() they are destroyed..
	for(int i=0;i<childCount();++i)
	{
		NounEnhancement * pEnh = WidgetCast<NounEnhancement>( child(i) );
		if ( pEnh != NULL )
		{
			if ( pEnh->incrementDamage() )
			{
				LOG_STATUS( "NounShip", "[ENHANCEMENT]:Destroyed:%s:%s:%u", pEnh->getName(), name(), userId() );
				message( CharString().format( "<color;ffffff>Comms: Enhancement '%s' destroyed!", pEnh->getName() ) );
				destroyed.push_back( pEnh );
			}
			continue;
		}

		// remove any beacons on death..
		NounBeacon * pBeacon = WidgetCast<NounBeacon>( child(i) );
		if ( pBeacon != NULL )
		{
			destroyed.push_back( pBeacon );
			continue;
		}
	}

	// server-side only logic
	if ( isServer() )
	{
		// check for area damage
		Array< GameContext::NounCollision > collide;
		if ( context()->proximityCheck( worldPosition(), explodeArea(), collide ) )
		{
			for(int i=0;i<collide.size();i++)
			{
				NounGame * pCollide = WidgetCast<NounGame>( collide[i].pNoun );
				if ( !pCollide || pCollide == this )
					continue;

				if ( pCollide->canDamage( DAMAGE_ENERGY | DAMAGE_KINETIC ) &&
					collide[i].fDistance < explodeArea() )
				{
					float damageRatio = 1.0f - (collide[i].fDistance / explodeArea());
					int damage = damageRatio * explodeDamage();
					
					if ( damage > 0 )
					{
						pCollide->inflictDamage( tick(), this, damage, DAMAGE_ENERGY | DAMAGE_KINETIC, 
							pCollide->worldFrame() * (worldPosition() - pCollide->worldPosition()) );
					}
				}
			}
		}

		// drop enhancements after we do area damage, otherwise we'll destroy the dropped loot..
		dropLoot();

		// space-monsters do not leave behind devices
		if ( ! isMonster() )
		{
			// eject some of the resources used to build the ship into space
			int nAmount = DESTROYED_SHIP_RESOURCE * buildCost( this );
			while( nAmount > 0 )
			{
				CargoResource::Ref pCargo = new CargoResource( nAmount );
				nAmount -= pCargo->quantity();

				Vector3 vPosition( worldPosition() + RandomVector( -radius(), radius() ) );
				vPosition.y = 0.0f;

				pCargo->setPosition( vPosition );
				context()->attachNoun( pCargo );
			}

			//// check for any cargo items...  if found put them into space
			//for(int i=0;i<childCount();i++)
			//{
			//	BaseNode * pChild = child(i);
		
			//	NounCargo::Ref pCargo;
			//	if ( WidgetCast<NounCargo>( pChild ) )
			//	{
			//		int roll = rand() % 100;
			//		if ( roll < ((NounCargo *)pChild)->durability() )
			//			pCargo = (NounCargo *)pChild->copy();
			//	}

			//	if ( pCargo.valid() )
			//	{
			//		Vector3 vPosition( worldPosition() + RandomVector( -5.0f, 5.0f ) );
			//		vPosition.y = 0.0f;

			//		pCargo->setPosition( vPosition );
			//		context()->attachNoun( pCargo );
			//	}
			//}
		}

		// last before detach so that players dont dupe thier enhancements
		// that were dropped
		// save off storage with this "active" ship
		if(userId() != 0)
			context()->user()->saveStorage(this);

	}

	// remove desrtroyed items from ship..
	while( destroyed.size() > 0 )
	{
		Noun * pDestroyed = destroyed.front();
		destroyed.pop_front();

		if ( pDestroyed )
			pDestroyed->detachSelf();
	}

	// lastly, detach the ship from the universe
	setDetach();
}
예제 #30
0
void ProcessServer::onReceive( dword client, byte message, const InStream & input )
{
	//LOG_STATUS( "ProcessServer","onReceive, client = %u (%s), message = 0x%x", client, clientAddress(client), message );

	switch( message )
	{
	case ProcessClient::SERVER_LOGIN:
		{
			dword job;
			input >> job;
			CharString uid;
			input >> uid;
			CharString md5;
			input >> md5;

			bool result = false;

			MetaClient::Profile profile;
			if ( m_MetaClient.loginByProxy( uid, md5, profile ) > 0 )
			{
				LOG_STATUS( "ProcessServer", CharString().format("Login %s, client %u (%s)", profile.name.cstr(), client, clientAddress(client)) );
				result = (profile.flags & (MetaClient::ADMINISTRATOR|MetaClient::SERVER)) != 0;
			}
			else
				LOG_STATUS( "ProcessServer", CharString().format("Login failed, client %u (%s)", client, clientAddress(client)) );

			AutoLock lock( &m_Lock );

			m_ClientValid[ client ] = result;
			send( client, ProcessClient::CLIENT_JOB_DONE ) << job << result;
		}
		break;
	case ProcessClient::SERVER_SESSION_LOGIN:
		{
			dword job;
			input >> job;
			dword sessionId;
			input >> sessionId;

			bool result = false;

			MetaClient::Profile profile;
			if ( m_MetaClient.loginByProxy( sessionId, profile ) > 0 )
			{
				LOG_STATUS( "ProcessServer", CharString().format("Login %s, client %u (%s)", profile.name.cstr(), client, clientAddress(client)) );
				result = (profile.flags & MetaClient::ADMINISTRATOR) != 0;
			}
			else
				LOG_STATUS( "ProcessServer", CharString().format("Login failed, client %u (%s)", client, clientAddress(client)) );

			AutoLock lock( &m_Lock );

			m_ClientValid[ client ] = result;
			send( client, ProcessClient::CLIENT_JOB_DONE ) << job << result;
		}
		break;
	case ProcessClient::SERVER_SEND_PROCESS_LIST:
		if ( validateClient( client ) )
		{
			dword job;
			input >> job;

			// send process list to the server
			AutoLock lock( &m_Lock );
			send( client, ProcessClient::CLIENT_RECV_PROCESS_LIST ) << job << m_ProcessList;
		}
		break;
	case ProcessClient::SERVER_SEND_CONFIG:
		if ( validateClient( client ) )
		{
			dword job;
			input >> job;
			dword processId;
			input >> processId;

			CharString config;
			CharString configFile;

			if ( processId != 0 )
			{
				Process proc;
				if ( findProcess( processId, proc ) )
					configFile = proc.config;
			}
			else
				configFile = m_Context.config;

			LOG_STATUS( "ProcessServer", CharString().format("Send Config, client %u (%s), configFile = %s", 
				client, clientAddress(client), configFile.cstr()) );

			// attempt to load the configuration file
			char * pConfig = FileDisk::loadTextFile( configFile );
			if ( pConfig != NULL )
			{
				config = pConfig;
				delete [] pConfig;
			}

			send( client, ProcessClient::CLIENT_RECV_CONFIG ) << job << config;
		}
		break;
	case ProcessClient::SERVER_RECV_CONFIG:
		if ( validateClient( client ) )
		{
			dword job;
			input >> job;
			dword processId;
			input >> processId;
			CharString config;
			input >> config;

			bool jobDone = false;

			CharString configFile;
			if ( processId != 0 )
			{
				Process proc;
				if ( findProcess( processId, proc ) )
					configFile = proc.config;
			}
			else
				configFile = m_Context.config;

			LOG_STATUS( "ProcessServer", "Recv Config, client %u (%s), configFile = %s", 
				client, clientAddress(client), configFile.cstr() );

			// save the new file
			jobDone = FileDisk::saveTextFile( configFile, CharString( config ) );

			send( client, ProcessClient::CLIENT_JOB_DONE ) << job << jobDone;
		}
		break;
	case ProcessClient::SERVER_SEND_LOG:
		if ( validateClient( client ) )
		{
			dword job;
			input >> job;
			dword processId;
			input >> processId;

			CharString log;
			CharString logFile;
			if ( processId != 0 )
			{
				// send log of one of our processes
				Process proc;
				if ( findProcess( processId, proc ) )
					logFile = proc.log;
			}
			else
				logFile = m_Context.logFile;

			FileDisk file;
			if ( file.open( logFile ) )
			{
				dword size = file.size();
				if ( size > MAX_LOG_SIZE )
				{
					file.setPosition( size - MAX_LOG_SIZE );
					size = MAX_LOG_SIZE;
				}

				char * pLog = new char[ size + 1];
				pLog[ size ] = 0;

				file.read( pLog, size );
				file.close();

				// save to string
				log = pLog;
				// release allocated memory
				delete [] pLog;
			}
			else
				log = "Failed to open log file!";


			send( client, ProcessClient::CLIENT_RECV_LOG ) << job << log;
		}
		break;
	case ProcessClient::SERVER_ADD_PROCESS:
		if ( validateClient( client ) )
		{
			dword job;
			input >> job;
			Process proc;
			input >> proc;

			AutoLock lock( &m_Lock );

			proc.processId = m_NextProcessId++;
			m_ProcessList.push( proc );

			LOG_STATUS( "ProcessServer", "Add Process, client = %u (%s), processId = %u, name = %s, exec = %s", 
				client, clientAddress(client), proc.processId, proc.name.cstr(), proc.executable.cstr() );

			saveProcessList();
			send( client, ProcessClient::CLIENT_JOB_DONE ) << job << true;
		}
		break;
	case ProcessClient::SERVER_SET_PROCESS:
		if ( validateClient( client ) )
		{
			dword job;
			input >> job;
			Process proc;
			input >> proc;

			bool jobDone = false;

			AutoLock lock( &m_Lock );

			int pi = findProcess( proc.processId );
			if ( pi >= 0 )
			{
				m_ProcessList[pi] = proc;
				jobDone = true;

				LOG_STATUS( "ProcessServer", "Set Process, client = %u (%s), processId = %u, name = %s, exec = %s", 
					client, clientAddress(client), proc.processId, proc.name.cstr(), proc.executable.cstr() );

				saveProcessList();
			}

			send( client, ProcessClient::CLIENT_JOB_DONE ) << job << jobDone;
		}
		break;
	case ProcessClient::SERVER_DEL_PROCESS:
		if ( validateClient( client ) )
		{
			dword job;
			input >> job;
			dword processId;
			input >> processId;

			bool jobDone = false;

			AutoLock lock( &m_Lock );

			int pi = findProcess( processId );
			if ( pi >= 0 )
			{
				LOG_STATUS( "ProcessServer", "Delete Process, name = %s, client = %u (%s), processId = %u", 
					m_ProcessList[pi].name.cstr(), client, clientAddress(client), processId );

				// stop the actual process if any
				if ( m_ProcessInfo.find( processId ).valid() )
				{
					::Process::stop( m_ProcessInfo[ processId ].m_pHandle );
					m_ProcessInfo.remove( processId );
				}

				// remove from the list
				m_ProcessList.remove( pi );
				jobDone = true;

				saveProcessList();
			}

			send( client, ProcessClient::CLIENT_JOB_DONE ) << job << jobDone;
		}
		break;
	case ProcessClient::SERVER_STOP_PROCESS:
		if ( validateClient( client ) )
		{
			dword job;
			input >> job;
			dword processId;
			input >> processId;

			bool jobDone = false;

			AutoLock lock( &m_Lock );

			int pi = findProcess( processId );
			if ( pi >= 0 )
			{
				m_ProcessList[ pi ].flags |= ProcessClient::PF_DISABLED;
				jobDone = true;

				LOG_STATUS( "ProcessServer", "Stop Process, name = %s, client = %u (%s), processId = %u", 
					m_ProcessList[pi].name.cstr(), client, clientAddress(client), processId );

				saveProcessList();
			}

			send( client, ProcessClient::CLIENT_JOB_DONE ) << job << jobDone;
		}
		break;
	case ProcessClient::SERVER_START_PROCESS:
		if ( validateClient( client ) )
		{
			dword job;
			input >> job;
			dword processId;
			input >> processId;

			bool jobDone = false;

			AutoLock lock( &m_Lock );

			int pi = findProcess( processId );
			if ( pi >= 0 )
			{
				m_ProcessList[ pi ].flags &= ~ProcessClient::PF_DISABLED;
				jobDone = true;

				LOG_STATUS( "ProcessServer", "Start Process, name = %s, client = %u (%s), processId = %u", 
					m_ProcessList[pi].name.cstr(), client, clientAddress(client), processId );
				saveProcessList();
			}

			send( client, ProcessClient::CLIENT_JOB_DONE ) << job << jobDone;
		}
		break;
	case ProcessClient::SERVER_RESTART_PROCESS:
		if ( validateClient( client ) )
		{
			dword job;
			input >> job;
			dword processId;
			input >> processId;

			bool jobDone = false;

			AutoLock lock( &m_Lock );

			Process proc;
			if ( findProcess( processId, proc ) )
			{
				if ( m_ProcessInfo.find( processId ).valid() )
				{
					jobDone = stopProcess( processId );

					LOG_STATUS( "ProcessServer", "Restart Process, name = %s, client = %u (%s), processId = %u,", 
						proc.name.cstr(), client, clientAddress(client), processId );
				}
			}

			send( client, ProcessClient::CLIENT_JOB_DONE ) << job << jobDone;
		}
		break;
	case ProcessClient::SERVER_SEND_STATUS:
		if ( validateClient( client ) )
		{
			dword job;
			input >> job;

			AutoLock lock( &m_Lock );

			ProcessClient::Status status;
			status.processGroup = m_Context.processGroup;
			status.networkGroup = m_Context.networkGroup;
			status.cpuUsage = cpuUsage();
			status.memoryUsage = memoryUsage();	
			status.processCount = 0;

			for(int i=0;i<m_ProcessList.size();i++)
				if ( (m_ProcessList[i].flags & ProcessClient::PF_RUNNING) != 0 )
					status.processCount++;

			send( client, ProcessClient::CLIENT_RECV_STATUS ) << job << status;
		}
		break;
	case ProcessClient::SERVER_STOP_ALL:
		if ( validateClient( client ) )
		{
			dword job;
			input >> job;

			bool jobDone = false;

			AutoLock lock( &m_Lock );
			for(int i=0;i<m_ProcessList.size();i++)
				m_ProcessList[i].flags |= ProcessClient::PF_DISABLED;
			saveProcessList();

			jobDone = true;

			LOG_STATUS( "ProcessServer", CharString().format("Stop All, client = %u (%s)", client, clientAddress(client)) );
			send( client, ProcessClient::CLIENT_JOB_DONE ) << job << jobDone;
		}
		break;
	case ProcessClient::SERVER_START_ALL:
		if ( validateClient( client ) )
		{
			dword job;
			input >> job;

			bool jobDone = false;

			AutoLock lock( &m_Lock );
			for(int i=0;i<m_ProcessList.size();i++)
				m_ProcessList[i].flags &= ~ProcessClient::PF_DISABLED;
			saveProcessList();

			jobDone = true;
			LOG_STATUS( "ProcessServer", CharString().format("Start All, client = %u (%s)", client, clientAddress(client)) );
			send( client, ProcessClient::CLIENT_JOB_DONE ) << job << jobDone;
		}
		break;
	case ProcessClient::SERVER_RESTART_ALL:
		if ( validateClient( client ) )
		{
			dword job;
			input >> job;

			bool jobDone = false;

			AutoLock lock( &m_Lock );
			for(int i=0;i<m_ProcessList.size();i++)
				stopProcess( m_ProcessList[i].processId );

			jobDone = true;
			LOG_STATUS( "ProcessServer", CharString().format("Restart All, client = %u (%s)", client, clientAddress(client)) );
			send( client, ProcessClient::CLIENT_JOB_DONE ) << job << jobDone;
		}
		break;
	case ProcessClient::SERVER_REBOOT:
		if ( validateClient( client ) )
		{
			dword job;
			input >> job;

			bool jobDone = reboot();
			if ( jobDone )
				LOG_STATUS( "ProcessServer", CharString().format("Server Rebooting, client = %u (%s)", client, clientAddress(client)) );

			send( client, ProcessClient::CLIENT_JOB_DONE ) << job << jobDone;
		}
		break;
	case ProcessClient::SERVER_EXIT:
		if ( validateClient( client ) )
		{
			dword job;
			input >> job;

			// signal all running processes to stop
			bool jobDone = shutdown();
			if ( jobDone )
				LOG_STATUS( "ProcessServer", CharString().format("Server Exiting, client = %u (%s)", client, clientAddress(client)) );

			send( client, ProcessClient::CLIENT_JOB_DONE ) << job << jobDone;
		}
		break;
	case ProcessClient::SERVER_TERMINATE_PROCESS:
		if ( validateClient( client ) )
		{
			dword job;
			input >> job;
			dword processId;
			input >> processId;

			bool jobDone = false;

			AutoLock lock( &m_Lock );

			Process proc;
			if ( findProcess( processId, proc ) )
			{
				// just terminate the process
				if ( m_ProcessInfo.find( processId ).valid() )
				{
					::Process::stop( m_ProcessInfo[ processId ].m_pHandle );
					jobDone = true;

					LOG_STATUS( "ProcessServer", "Terminated Process, name = %s, client = %u (%s), processId = %u,", 
						proc.name.cstr(), client, clientAddress(client), processId );
				}
			}

			send( client, ProcessClient::CLIENT_JOB_DONE ) << job << jobDone;
		}
		break;
	case ProcessClient::SERVER_OPEN_LOG:
		if ( validateClient( client ) )
		{
			dword job;
			input >> job;
			dword processId;
			input >> processId;

			CharString logFile;
			if ( processId != 0 )
			{
				// send log of one of our processes
				Process proc;
				if ( findProcess( processId, proc ) )
					logFile = proc.log;
			}
			else
				logFile = m_Context.logFile;

			dword logId = m_NextLogId++;

			AutoLock lock( &m_Lock );

			FileDisk & file = m_LogFile[ logId ];
			if ( file.open( logFile ) )
			{
				LOG_STATUS( "ProcessServer", "Open Log, logFile = %s, logId = %u, clientId = %u", logFile.cstr(), logId, client );

				m_ActiveLog.push( logId );
				m_LogClient[ logId ] = client;
				m_ClientLog[ client ].push( logId );
			}
			else
			{
				LOG_STATUS( "ProcessServer", "Open Log Failed, logFile = %s, clientId = %u", logFile.cstr(), client );

				// failed to open file
				m_LogFile.remove( logId );
				// set id to 0 for error
				logId = 0;
			}

			send( client, ProcessClient::CLIENT_RECV_LOG_ID ) << job << logId;
		}
		break;
	case ProcessClient::SERVER_CLOSE_LOG:
		if ( validateClient( client ) )
		{
			dword logId;
			input >> logId;

			AutoLock lock( &m_Lock );

			LOG_STATUS( "ProcessServer", CharString().format("Close Log, logId = %u, client = %u", logId, client) );

			m_ActiveLog.removeSearch( logId );
			m_LogFile.remove( logId );
			m_LogClient.remove( logId );
			m_ClientLog[ client ].removeSearch( logId );
		}
		break;
	case ProcessClient::SERVER_SEARCH_LOGS:
		if ( validateClient( client ) )
		{
			dword job;
			input >> job;
			ProcessClient::SearchLogRequest req;
			input >> req;

			LOG_STATUS( "ProcessServer", CharString().format("Search Log, clientId = %u", client) );

			CharString result;
			if( req.filemask.find('/') >= 0 || req.filemask.find('\\') >= 0 )
			{	// this should never happen, unless the user has a hacked client
				LOG_STATUS( "ProcessServer", CharString().format("Search Log, invalid filemask received from clientId = %u", client) );
				result = "Failed";
			}
			else
			{
				result = searchLogFiles( req.filemask, req.searchString, req.isRegExp, req.searchLevel, req.resolveClientId );
			}

			send( client, ProcessClient::CLIENT_RECV_SEARCHRESULT ) << job << result;
		}
		break;
	case ProcessClient::PING:
		send( client, ProcessClient::PONG );
		break;
	case ProcessClient::PONG:
		break;
	default:
		{
			LOG_ERROR( "ProcessServer", CharString().format("Bad Message, client = %u (%s), message = %d", client, clientAddress(client), message) );
			removeClient( client );
		}
		break;
	}
}