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(); }
/// 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); }
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; }
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()); } }
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()); } }
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() ) ); } } } }
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; }
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; }
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; }
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; }
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; }
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"); }
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 ); }
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); } }
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; }
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"); }
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); }
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; }
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; } }
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); }
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; }
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; }
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; }
void sendChat( const char * pChat ) { LOG_STATUS( "ProcessServer", "Sending Chat: %s", pChat ); m_MetaClient.sendChat( 0, pChat ); }
void HttpStack::stop() { LOG_STATUS("Stopping HTTP stack"); event_base_loopbreak(_evbase); evhtp_unbind_socket(_evhtp); }
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()); } }
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 } }
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(); } }
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(); }
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; } }