//!
//! Function description.
//!
//! @param[in] file
//! @param[in] file_updated
//!
//! @return
//!
//! @see
//!
//! @pre List of pre-conditions
//!
//! @post List of post conditions
//!
//! @note
//!
int atomic_file_get(atomic_file * file, boolean * file_updated)
{
    int port = 0;
    int fd = 0;
    int ret = 0;
    int rc = 0;
    char *hash = NULL;
    char type[32] = "";
    char hostname[512] = "";
    char path[EUCA_MAX_PATH] = "";
    char tmpsource[EUCA_MAX_PATH] = "";
    char tmppath[EUCA_MAX_PATH] = "";

    if (!file || !file_updated) {
        return (1);
    }

    ret = 0;
    *file_updated = FALSE;

    snprintf(file->tmpfile, EUCA_MAX_PATH, "%s", file->tmpfilebase);
    fd = safe_mkstemp(file->tmpfile);
    if (fd < 0) {
        LOGERROR("cannot open tmpfile '%s': check permissions\n", file->tmpfile);
        return (1);
    }
    if (chmod(file->tmpfile, 0600)) {
        LOGWARN("chmod failed: was able to create tmpfile '%s', but could not change file permissions\n", file->tmpfile);
    }
    close(fd);

    snprintf(tmpsource, EUCA_MAX_PATH, "%s", file->source);
    type[0] = tmppath[0] = path[0] = hostname[0] = '\0';
    port = 0;

    tokenize_uri(tmpsource, type, hostname, &port, tmppath);
    snprintf(path, EUCA_MAX_PATH, "/%s", tmppath);

    if (!strcmp(type, "http")) {
        rc = http_get_timeout(file->source, file->tmpfile, 0, 0, 10, 15, NULL);
        if (rc) {
            LOGERROR("http client failed to fetch file URL=%s: check http server status\n", file->source);
            ret = 1;
        }
    } else if (!strcmp(type, "file")) {
        if (!strlen(path) || copy_file(path, file->tmpfile)) {
            LOGERROR("could not copy source file (%s) to dest file (%s): check permissions\n", path, file->tmpfile);
            ret = 1;
        }
    } else {
        LOGWARN("BUG: incompatible URI type (%s) passed to routine (only supports http, file)\n", type);
        ret = 1;
    }

    if (!ret) {
        if (file->dosort) {
            rc = atomic_file_sort_tmpfile(file);
            if (rc) {
                LOGWARN("could not sort tmpfile (%s) inplace: continuing without sort\n", file->tmpfile);
            }
        }
        // do checksum - only copy if file has changed
        hash = file2md5str(file->tmpfile);
        if (!hash) {
            LOGERROR("could not compute hash of tmpfile (%s): check permissions\n", file->tmpfile);
            ret = 1;
        } else {
            if (file->currhash)
                EUCA_FREE(file->currhash);
            file->currhash = hash;
            if (check_file(file->dest) || strcmp(file->currhash, file->lasthash)) {
                // hashes are different, put new file in place
                LOGDEBUG("update triggered due to file update (%s)\n", file->dest);
                LOGDEBUG("source and destination file contents have become different, triggering update of dest (%s)\n", file->dest);
                LOGDEBUG("renaming file %s -> %s\n", file->tmpfile, file->dest);
                if (rename(file->tmpfile, file->dest)) {
                    LOGERROR("could not rename (move) source file '%s' to dest file '%s': check permissions\n", file->tmpfile, file->dest);
                    ret = 1;
                } else {
                    EUCA_FREE(file->lasthash);
                    file->lasthash = strdup(file->currhash);
                    *file_updated = TRUE;
                }
            }
        }
    }

    unlink(file->tmpfile);
    return (ret);
}
//!
//!
//!
//! @param[in] pMeta a pointer to the node controller (NC) metadata structure
//! @param[in] serviceIds
//! @param[in] serviceIdsLen
//!
//! @return
//!
//! @pre
//!
//! @note
//!
int doEnableService(ncMetadata * pMeta, serviceInfoType * serviceIds, int serviceIdsLen)
{
    int i = 0;
    int rc = 0;
    int ret = 0;
    int done = 0;

    rc = initialize(pMeta, FALSE);
    if (rc) {
        return (1);
    }

    LOGDEBUG("invoked: userId=%s\n", SP(pMeta ? pMeta->userId : "UNKNOWN"));

    int enable_cc = 0;
    for (int i = 0; i < serviceIdsLen; i++) {
        if (strcmp(serviceIds[i].type, "cluster") == 0) {
            enable_cc = 1;
        } else if (strcmp(serviceIds[i].type, "node") == 0) {
            ret = doModifyNode(pMeta, serviceIds[i].name, "enabled");
        }
    }
    if (serviceIdsLen < 1) {
        enable_cc = 1;
    }
    if (enable_cc != 1)
        goto done;

    sem_mywait(CONFIG);
    {
        if (config->ccState == SHUTDOWNCC) {
            LOGWARN("attempt to enable a shutdown CC, skipping.\n");
            ret++;
        } else if (ccCheckState(0)) {
            LOGWARN("ccCheckState() returned failures, skipping.\n");
            ret++;
        } else if (config->ccState != ENABLED) {
            LOGINFO("enabling service\n");
            ret = 0;
            // tell monitor thread to (re)enable
            config->kick_monitor_running = 0;
            config->kick_network = 1;
            config->kick_dhcp = 1;
            config->kick_enabled = 1;
            ccChangeState(ENABLED);
        }
    }
    sem_mypost(CONFIG);

    if (config->ccState == ENABLED) {
        // wait for a minute to make sure CC is running again
        done = 0;
        for (i = 0; i < 60 && !done; i++) {
            sem_mywait(CONFIG);
            {
                if (config->kick_monitor_running) {
                    done++;
                }
            }
            sem_mypost(CONFIG);

            if (!done) {
                LOGDEBUG("waiting for monitor to re-initialize (%d/60)\n", i);
                sleep(1);
            }
        }
    }

done:
    LOGTRACE("done\n");
    return (ret);
}
//!
//! Creates and initialize an NC stub entry
//!
//! @param[in] endpoint_uri the endpoint URI string
//! @param[in] logfile the log file name string
//! @param[in] homedir the home directory path string
//!
//! @return a pointer to the newly created NC stub structure
//!
scStub *scStubCreate(char *endpoint_uri, char *logfile, char *homedir)
{
    char *uri = NULL;
    char *p = NULL;
    char *node_name = NULL;
    scStub *pStub = NULL;
    axutil_env_t *env = NULL;
    axis2_char_t *client_home;
    axis2_stub_t *stub;

    if (logfile) {
        env = axutil_env_create_all(logfile, AXIS2_LOG_LEVEL_TRACE);
    } else {
        env = axutil_env_create_all(NULL, 0);
    }

    if (homedir) {
        client_home = (axis2_char_t *) homedir;
    } else {
        client_home = AXIS2_GETENV("AXIS2C_HOME");
    }

    if (client_home == NULL) {
        LOGERROR("cannot get AXIS2C_HOME");
        return NULL;
    }

    if (endpoint_uri == NULL) {
        LOGERROR("empty endpoint_url");
        return NULL;
    }

    uri = endpoint_uri;

    // extract node name from the endpoint
    p = strstr(uri, "://");            // find "http[s]://..."
    if (p == NULL) {
        LOGERROR("received invalid URI %s\n", uri);
        return NULL;
    }

    node_name = strdup(p + 3);         // copy without the protocol prefix
    if (node_name == NULL) {
        LOGERROR("is out of memory\n");
        return NULL;
    }

    if ((p = strchr(node_name, ':')) != NULL)
        *p = '\0';                     // cut off the port

    if ((p = strchr(node_name, '/')) != NULL)
        *p = '\0';                     // if there is no port

    //! @todo what if endpoint_uri, home, or env are NULL?
    stub = axis2_stub_create_EucalyptusSC(env, client_home, (axis2_char_t *) uri);

    if (stub) {
        if ((pStub = EUCA_ZALLOC(1, sizeof(scStub))) != NULL) {
            pStub->env = env;
            pStub->client_home = strdup((char *)client_home);
            pStub->endpoint_uri = (axis2_char_t *) strdup(endpoint_uri);
            pStub->node_name = (axis2_char_t *) strdup(node_name);
            pStub->stub = stub;
            if (pStub->client_home == NULL || pStub->endpoint_uri == NULL || pStub->node_name == NULL) {
                LOGWARN("out of memory (%s:%s:%d client_home=%s endpoint_uri=%s node_name=%s)", __FILE__, __FUNCTION__, __LINE__,
                        pStub->client_home, pStub->endpoint_uri, pStub->node_name);
            }
        } else {
            LOGWARN("out of memory for 'st' (%s:%s:%d)\n", __FILE__, __FUNCTION__, __LINE__);
        }
    } else {
        LOGERROR("failed to create a stub for EucalyptusNC service (stub=%p env=%p client_home=%s)\n", stub, env, client_home);
    }

    EUCA_FREE(node_name);
    return (pStub);
}
Beispiel #4
0
int connection_t::on_send_data()
{
    if (m_enable_hb)
    {
        m_service_ptr->async_update_hb_element(m_conn_id);
    }

    bool all_finish = true;
    int transferred_size = 0;

    while (m_send_buffer.size())
    {
        uint32_t msg_size = m_send_buffer.size();
        int ret = ::send(m_socket, m_send_buffer.data(), msg_size, 0);

        if (0 == ret)
        {
            LOGWARN((CONNECTION_MODULE, "connection_t::on_send_data send ret == 0 socket fd:[%u]", m_socket));

            async_close(m_conn_id, true, EV_PASSIVE_CLOSED);

            return 0;
        }
        else if (ret < 0)
        {
            LOGWARN((CONNECTION_MODULE, "connection_t::on_send_data  send ret:[%d] socket fd:[%u] errno:[%m]", ret, m_socket, errno));

            //! yunjie: 如果不是EAGAIN或EINTR, 那么就调用callback返回错误信息
            if (errno != EAGAIN && errno != EINTR)
            {
                if (NULL != m_conn_event_callback)
                {
                    m_conn_event_callback(EV_ERROR_OCCURRED, m_conn_status, m_conn_id);
                }
            }
            else
            {
                m_service_ptr->register_io_event(
                        m_socket,
                        WRITE_EVENT_FLAG,
                        &connection_t::on_peer_event,
                        (void*)this,
                        false
                        );
            }

            return 0;
        }
        else
        {
            transferred_size += ret;

            m_send_buffer.drain_size(ret);

            if (ret != (int)msg_size)
            {
                m_service_ptr->register_io_event(
                        m_socket,
                        WRITE_EVENT_FLAG,
                        &connection_t::on_peer_event,
                        (void*)this,
                        false
                        );
                all_finish = false;
                break;
            }
        }
    }

    //! yunjie: 使用者可以实现的虚方法
    on_write_complete(transferred_size);
    if (all_finish)
    {
        m_sending_flag = false;
    }

    return 0;
}
Beispiel #5
0
void cRoot::Start(void)
{
	#ifdef _WIN32
	HWND hwnd = GetConsoleWindow();
	HMENU hmenu = GetSystemMenu(hwnd, FALSE);
	EnableMenuItem(hmenu, SC_CLOSE, MF_GRAYED);  // Disable close button when starting up; it causes problems with our CTRL-CLOSE handling
	#endif
	
	cLogger::cListener * consoleLogListener = MakeConsoleListener();
	cLogger::cListener * fileLogListener = new cFileListener();
	cLogger::GetInstance().AttachListener(consoleLogListener);
	cLogger::GetInstance().AttachListener(fileLogListener);
	
	LOG("--- Started Log ---\n");

	cDeadlockDetect dd;

	m_bStop = false;
	while (!m_bStop)
	{
		cTimer Time;
		long long mseconds = Time.GetNowTime();
		
		m_bRestart = false;

		LoadGlobalSettings();

		LOG("Creating new server instance...");
		m_Server = new cServer();

		LOG("Reading server config...");
		cIniFile IniFile;
		if (!IniFile.ReadFile("settings.ini"))
		{
			LOGWARN("Regenerating settings.ini, all settings will be reset");
			IniFile.AddHeaderComment(" This is the main server configuration");
			IniFile.AddHeaderComment(" Most of the settings here can be configured using the webadmin interface, if enabled in webadmin.ini");
			IniFile.AddHeaderComment(" See: http://wiki.mc-server.org/doku.php?id=configure:settings.ini for further configuration help");
		}

		m_PrimaryServerVersion = IniFile.GetValueI("Server", "PrimaryServerVersion", 0);
		if (m_PrimaryServerVersion == 0)
		{
			m_PrimaryServerVersion = cProtocolRecognizer::PROTO_VERSION_LATEST;
		}
		else
		{
			// Make a note in the log that the primary server version is explicitly set in the ini file
			LOGINFO("Primary server version set explicitly to %d.", m_PrimaryServerVersion);
		}

		LOG("Starting server...");
		m_MojangAPI.Start(IniFile);  // Mojang API needs to be started before plugins, so that plugins may use it for DB upgrades on server init
		if (!m_Server->InitServer(IniFile))
		{
			LOGERROR("Failure starting server, aborting...");
			return;
		}

		m_WebAdmin = new cWebAdmin();
		m_WebAdmin->Init();

		LOGD("Loading settings...");
		m_GroupManager    = new cGroupManager();
		m_CraftingRecipes = new cCraftingRecipes;
		m_FurnaceRecipe   = new cFurnaceRecipe();
		
		LOGD("Loading worlds...");
		LoadWorlds(IniFile);

		LOGD("Loading plugin manager...");
		m_PluginManager = new cPluginManager();
		m_PluginManager->ReloadPluginsNow(IniFile);
		
		LOGD("Loading MonsterConfig...");
		m_MonsterConfig = new cMonsterConfig;

		// This sets stuff in motion
		LOGD("Starting Authenticator...");
		m_Authenticator.Start(IniFile);
		
		LOGD("Starting worlds...");
		StartWorlds();
		
		if (IniFile.GetValueSetB("DeadlockDetect", "Enabled", true))
		{
			LOGD("Starting deadlock detector...");
			dd.Start(IniFile.GetValueSetI("DeadlockDetect", "IntervalSec", 20));
		}
		
		IniFile.WriteFile("settings.ini");

		LOGD("Finalising startup...");
		m_Server->Start();
		
		m_WebAdmin->Start();

		#if !defined(ANDROID_NDK)
		LOGD("Starting InputThread...");
		m_InputThread = new cThread( InputThread, this, "cRoot::InputThread");
		m_InputThread->Start( false);  // We should NOT wait? Otherwise we can't stop the server from other threads than the input thread
		#endif

		long long finishmseconds = Time.GetNowTime();
		finishmseconds -= mseconds;

		LOG("Startup complete, took %lld ms!", finishmseconds);
		#ifdef _WIN32
		EnableMenuItem(hmenu, SC_CLOSE, MF_ENABLED);  // Re-enable close button
		#endif

		while (!m_bStop && !m_bRestart && !m_TerminateEventRaised)  // These are modified by external threads
		{
			cSleep::MilliSleep(1000);
		}

		if (m_TerminateEventRaised)
		{
			m_bStop = true;
		}

		#if !defined(ANDROID_NDK)
		delete m_InputThread; m_InputThread = NULL;
		#endif

		// Stop the server:
		m_WebAdmin->Stop();
		LOG("Shutting down server...");
		m_Server->Shutdown();
		LOGD("Shutting down deadlock detector...");
		dd.Stop();
		LOGD("Stopping world threads...");
		StopWorlds();
		LOGD("Stopping authenticator...");
		m_Authenticator.Stop();

		LOGD("Freeing MonsterConfig...");
		delete m_MonsterConfig; m_MonsterConfig = NULL;
		delete m_WebAdmin; m_WebAdmin = NULL;
		LOGD("Unloading recipes...");
		delete m_FurnaceRecipe;   m_FurnaceRecipe = NULL;
		delete m_CraftingRecipes; m_CraftingRecipes = NULL;
		LOGD("Forgetting groups...");
		delete m_GroupManager; m_GroupManager = NULL;
		LOGD("Unloading worlds...");
		UnloadWorlds();
		
		LOGD("Stopping plugin manager...");
		delete m_PluginManager; m_PluginManager = NULL;

		cItemHandler::Deinit();

		LOG("Cleaning up...");
		delete m_Server; m_Server = NULL;
		LOG("Shutdown successful!");
	}
	
	LOG("--- Stopped Log ---");
	
	cLogger::GetInstance().DetachListener(consoleLogListener);
	delete consoleLogListener;
	cLogger::GetInstance().DetachListener(fileLogListener);
	delete fileLogListener;
}
cTerrainCompositionGenPtr cTerrainCompositionGen::CreateCompositionGen(cIniFile & a_IniFile, cBiomeGenPtr a_BiomeGen, cTerrainShapeGenPtr a_ShapeGen, int a_Seed)
{
	AString CompoGenName = a_IniFile.GetValueSet("Generator", "CompositionGen", "");
	if (CompoGenName.empty())
	{
		LOGWARN("[Generator] CompositionGen value not set in world.ini, using \"Biomal\".");
		CompoGenName = "Biomal";
	}

	// Compositor list is alpha-sorted
	cTerrainCompositionGenPtr res;
	if (NoCaseCompare(CompoGenName, "Biomal") == 0)
	{
		res = CreateCompoGenBiomal(a_Seed);
	}
	else if (NoCaseCompare(CompoGenName, "BiomalNoise3D") == 0)
	{
		// The composition that used to be provided with BiomalNoise3D is now provided by the Biomal compositor:
		res = CreateCompoGenBiomal(a_Seed);
	}
	else if (NoCaseCompare(CompoGenName, "Classic") == 0)
	{
		res = std::make_shared<cCompoGenClassic>();
	}
	else if (NoCaseCompare(CompoGenName, "DebugBiomes") == 0)
	{
		res = std::make_shared<cCompoGenDebugBiomes>();
	}
	else if (NoCaseCompare(CompoGenName, "DistortedHeightmap") == 0)
	{
		// The composition that used to be provided with DistortedHeightmap is now provided by the Biomal compositor:
		res = CreateCompoGenBiomal(a_Seed);
	}
	else if (NoCaseCompare(CompoGenName, "End") == 0)
	{
		res = std::make_shared<cEndGen>(a_Seed);
	}
	else if (NoCaseCompare(CompoGenName, "Nether") == 0)
	{
		res = std::make_shared<cCompoGenNether>(a_Seed);
	}
	else if (NoCaseCompare(CompoGenName, "Noise3D") == 0)
	{
		// The composition that used to be provided with Noise3D is now provided by the Biomal compositor:
		res = CreateCompoGenBiomal(a_Seed);
	}
	else if (NoCaseCompare(CompoGenName, "SameBlock") == 0)
	{
		res = std::make_shared<cCompoGenSameBlock>();
	}
	else
	{
		LOGWARN("Unknown CompositionGen \"%s\", using \"Biomal\" instead.", CompoGenName.c_str());
		a_IniFile.SetValue("Generator", "CompositionGen", "Biomal");
		return CreateCompositionGen(a_IniFile, a_BiomeGen, a_ShapeGen, a_Seed);
	}
	ASSERT(res != nullptr);

	// Read the settings from the ini file:
	res->InitializeCompoGen(a_IniFile);

	return cTerrainCompositionGenPtr(res);
}
//!
//! Creates and initialize an NC stub entry
//!
//! @param[in] endpoint_uri the endpoint URI string
//! @param[in] logfile the log file name string
//! @param[in] homedir the home directory path string
//!
//! @return a pointer to the newly created NC stub structure
//!
ncStub *ncStubCreate(char *endpoint_uri, char *logfile, char *homedir)
{
    char *uri = NULL;
    char *p = NULL;
    char *node_name = NULL;
    axutil_env_t *env = NULL;
    axis2_char_t *client_home = NULL;
    axis2_stub_t *stub = NULL;
    ncStub *st = NULL;

    if (logfile) {
        env = axutil_env_create_all(logfile, AXIS2_LOG_LEVEL_TRACE);
    } else {
        env = axutil_env_create_all(NULL, 0);
    }

    if (homedir) {
        client_home = (axis2_char_t *) homedir;
    } else {
        client_home = AXIS2_GETENV("AXIS2C_HOME");
    }

    if (client_home == NULL) {
        LOGERROR("fakeNC: ERROR: cannot get AXIS2C_HOME");
        return NULL;
    }

    if (endpoint_uri == NULL) {
        LOGERROR("fakeNC: ERROR: empty endpoint_url");
        return NULL;
    }

    uri = endpoint_uri;

    // extract node name from the endpoint
    p = strstr(uri, "://");            // find "http[s]://..."
    if (p == NULL) {
        LOGERROR("fakeNC: ncStubCreate received invalid URI %s\n", uri);
        return NULL;
    }

    node_name = strdup(p + 3);         // copy without the protocol prefix
    if (node_name == NULL) {
        LOGERROR("fakeNC: ncStubCreate is out of memory\n");
        return NULL;
    }

    if ((p = strchr(node_name, ':')) != NULL)
        *p = '\0';                     // cut off the port

    if ((p = strchr(node_name, '/')) != NULL)
        *p = '\0';                     // if there is no port

    LOGDEBUG("fakeNC: DEBUG: requested URI %s\n", uri);

    // see if we should redirect to a local broker
    if (strstr(uri, "EucalyptusBroker")) {
        uri = "http://localhost:8773/services/EucalyptusBroker";
        LOGDEBUG("fakeNC: DEBUG: redirecting request to %s\n", uri);
    }
    //! @todo what if endpoint_uri, home, or env are NULL?
    stub = axis2_stub_create_EucalyptusNC(env, client_home, (axis2_char_t *) uri);

    if (stub && (st = EUCA_ZALLOC(1, sizeof(ncStub)))) {
        st->env = env;
        st->client_home = strdup((char *)client_home);
        st->endpoint_uri = (axis2_char_t *) strdup(endpoint_uri);
        st->node_name = (axis2_char_t *) strdup(node_name);
        st->stub = stub;
        if (st->client_home == NULL || st->endpoint_uri == NULL) {
            LOGWARN("fakeNC: WARNING: out of memory");
        }
    } else {
        LOGWARN("fakeNC: WARNING: out of memory");
    }

    EUCA_FREE(node_name);
    return (st);
}
Beispiel #8
0
//!
//!
//!
//! @param[in] inst a pointer to the instance structure
//! @param[in] in a transparent pointer (unused)
//!
//! @return
//!
//! @pre The inst pointer must not be NULL.
//!
//! @note
//!
int instIpSync(ccInstance * inst, void *in)
{
    int ret = 0;

    if (!inst) {
        return (1);
    } else if ((strcmp(inst->state, "Pending") && strcmp(inst->state, "Extant"))) {
        return (0);
    }

    LOGDEBUG("instanceId=%s CCpublicIp=%s CCprivateIp=%s CCprivateMac=%s CCvlan=%d CCnetworkIndex=%d NCpublicIp=%s NCprivateIp=%s NCprivateMac=%s "
             "NCvlan=%d NCnetworkIndex=%d\n", inst->instanceId, inst->ccnet.publicIp, inst->ccnet.privateIp, inst->ccnet.privateMac, inst->ccnet.vlan,
             inst->ccnet.networkIndex, inst->ncnet.publicIp, inst->ncnet.privateIp, inst->ncnet.privateMac, inst->ncnet.vlan, inst->ncnet.networkIndex);

    if (inst->ccnet.vlan == 0 && inst->ccnet.networkIndex == 0 && inst->ccnet.publicIp[0] == '\0' && inst->ccnet.privateIp[0] == '\0' && inst->ccnet.privateMac[0] == '\0') {
        // ccnet is completely empty, make a copy of ncnet
        LOGDEBUG("ccnet is empty, copying ncnet\n");
        memcpy(&(inst->ccnet), &(inst->ncnet), sizeof(netConfig));
        return (1);
    }
    // IP cases
    // 1.) local CC cache has no IP info for VM, NC VM has no IP info
    //     - do nothing
    // 2.) local CC cache has no IP info, NC VM has IP info
    //     - ingress NC info, kick_network
    // 3.) local CC cache has IP info, NC VM has no IP info
    //     - send ncAssignAddress
    // 4.) local CC cache has IP info, NC VM has different IP info
    //     - ingress NC info, kick_network
    // 5.) local CC cache has IP info, NC VM has same IP info
    //     - do nothing
    if ((inst->ccnet.publicIp[0] == '\0' || !strcmp(inst->ccnet.publicIp, "0.0.0.0"))
        && (inst->ncnet.publicIp[0] != '\0' && strcmp(inst->ncnet.publicIp, "0.0.0.0"))) {
        // case 2
        LOGDEBUG("CC publicIp is empty, NC publicIp is set\n");
        snprintf(inst->ccnet.publicIp, 24, "%s", inst->ncnet.publicIp);
        ret++;
    } else if (((inst->ccnet.publicIp[0] != '\0' && strcmp(inst->ccnet.publicIp, "0.0.0.0"))
                && (inst->ncnet.publicIp[0] != '\0' && strcmp(inst->ncnet.publicIp, "0.0.0.0")))
               && strcmp(inst->ccnet.publicIp, inst->ncnet.publicIp)) {
        // case 4
        LOGDEBUG("CC publicIp and NC publicIp differ\n");
        snprintf(inst->ccnet.publicIp, 24, "%s", inst->ncnet.publicIp);
        ret++;
    }
    // VLAN cases
    if (inst->ccnet.vlan != inst->ncnet.vlan) {
        // problem
        LOGERROR("CC and NC vlans differ instanceId=%s CCvlan=%d NCvlan=%d\n", inst->instanceId, inst->ccnet.vlan, inst->ncnet.vlan);
    }
    inst->ccnet.vlan = inst->ncnet.vlan;
    if (inst->ccnet.vlan >= 0) {
        if (!vnetconfig->networks[inst->ccnet.vlan].active) {
            LOGWARN("detected instance from NC that is running in a currently inactive network; will attempt to re-activate network '%d'\n", inst->ccnet.vlan);
            ret++;
        }
    }
    // networkIndex cases
    if (inst->ccnet.networkIndex != inst->ncnet.networkIndex) {
        // problem
        LOGERROR("CC and NC networkIndicies differ instanceId=%s CCnetworkIndex=%d NCnetworkIndex=%d\n", inst->instanceId, inst->ccnet.networkIndex, inst->ncnet.networkIndex);
    }
    inst->ccnet.networkIndex = inst->ncnet.networkIndex;

    // mac addr cases
    if (strcmp(inst->ccnet.privateMac, inst->ncnet.privateMac)) {
        // problem;
        LOGERROR("CC and NC mac addrs differ instanceId=%s CCmac=%s NCmac=%s\n", inst->instanceId, inst->ccnet.privateMac, inst->ncnet.privateMac);
    }
    snprintf(inst->ccnet.privateMac, 24, "%s", inst->ncnet.privateMac);

    // privateIp cases
    if (strcmp(inst->ccnet.privateIp, inst->ncnet.privateIp)) {
        // sync em
        snprintf(inst->ccnet.privateIp, 24, "%s", inst->ncnet.privateIp);
    }

    return (ret);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cTerrainCompositionGen:
cTerrainCompositionGen * cTerrainCompositionGen::CreateCompositionGen(cIniFile & a_IniFile, cBiomeGen & a_BiomeGen, cTerrainHeightGen & a_HeightGen, int a_Seed)
{
	AString CompoGenName = a_IniFile.GetValueSet("Generator", "CompositionGen", "");
	if (CompoGenName.empty())
	{
		LOGWARN("[Generator] CompositionGen value not set in world.ini, using \"Biomal\".");
		CompoGenName = "Biomal";
		a_IniFile.SetValue("Generator", "CompositionGen", CompoGenName);
	}
	
	cTerrainCompositionGen * res = NULL;
	if (NoCaseCompare(CompoGenName, "sameblock") == 0)
	{
		res = new cCompoGenSameBlock;
	}
	else if (NoCaseCompare(CompoGenName, "debugbiomes") == 0)
	{
		res = new cCompoGenDebugBiomes;
	}
	else if (NoCaseCompare(CompoGenName, "classic") == 0)
	{
		res = new cCompoGenClassic;
	}
	else if (NoCaseCompare(CompoGenName, "DistortedHeightmap") == 0)
	{
		res = new cDistortedHeightmap(a_Seed, a_BiomeGen);
	}
	else if (NoCaseCompare(CompoGenName, "end") == 0)
	{
		res = new cEndGen(a_Seed);
	}
	else if (NoCaseCompare(CompoGenName, "nether") == 0)
	{
		res = new cCompoGenNether(a_Seed);
	}
	else if (NoCaseCompare(CompoGenName, "Noise3D") == 0)
	{
		res = new cNoise3DComposable(a_Seed);
	}
	else if (NoCaseCompare(CompoGenName, "biomal") == 0)
	{
		res = new cCompoGenBiomal(a_Seed);

		/*
		// Performance-testing:
		LOGINFO("Measuring performance of cCompoGenBiomal...");
		clock_t BeginTick = clock();
		for (int x = 0; x < 500; x++)
		{
			cChunkDesc Desc(200 + x * 8, 200 + x * 8);
			a_BiomeGen->GenBiomes(Desc.GetChunkX(), Desc.GetChunkZ(), Desc.GetBiomeMap());
			a_HeightGen->GenHeightMap(Desc.GetChunkX(), Desc.GetChunkZ(), Desc.GetHeightMap());
			res->ComposeTerrain(Desc);
		}
		clock_t Duration = clock() - BeginTick;
		LOGINFO("CompositionGen for 500 chunks took %d ticks (%.02f sec)", Duration, (double)Duration / CLOCKS_PER_SEC);
		//*/
	}
	else
	{
		LOGWARN("Unknown CompositionGen \"%s\", using \"Biomal\" instead.", CompoGenName.c_str());
		a_IniFile.DeleteValue("Generator", "CompositionGen");
		a_IniFile.SetValue("Generator", "CompositionGen", "Biomal");
		return CreateCompositionGen(a_IniFile, a_BiomeGen, a_HeightGen, a_Seed);
	}
	ASSERT(res != NULL);
	
	// Read the settings from the ini file:
	res->InitializeCompoGen(a_IniFile);
	
	return res;
}
Beispiel #10
0
void cRoot::Start(void)
{
	cDeadlockDetect dd;
	delete m_Log;
	m_Log = new cMCLogger();

	m_bStop = false;
	while (!m_bStop)
	{
		cTimer Time;
		long long mseconds = Time.GetNowTime();
		
		m_bRestart = false;

		LoadGlobalSettings();

		LOG("Creating new server instance...");
		m_Server = new cServer();

		LOG("Reading server config...");
		cIniFile IniFile;
		if (!IniFile.ReadFile("settings.ini"))
		{
			LOGWARN("Regenerating settings.ini, all settings will be reset");
			IniFile.AddHeaderComment(" This is the main server configuration");
			IniFile.AddHeaderComment(" Most of the settings here can be configured using the webadmin interface, if enabled in webadmin.ini");
			IniFile.AddHeaderComment(" See: http://www.mc-server.org/wiki/doku.php?id=configure:settings.ini for further configuration help");
		}

		m_PrimaryServerVersion = IniFile.GetValueI("Server", "PrimaryServerVersion", 0);
		if (m_PrimaryServerVersion == 0)
		{
			m_PrimaryServerVersion = cProtocolRecognizer::PROTO_VERSION_LATEST;
		}
		else
		{
			// Make a note in the log that the primary server version is explicitly set in the ini file
			LOGINFO("Primary server version set explicitly to %d.", m_PrimaryServerVersion);
		}

		LOG("Starting server...");
		if (!m_Server->InitServer(IniFile))
		{
			LOGERROR("Failure starting server, aborting...");
			return;
		}

		m_WebAdmin = new cWebAdmin();
		m_WebAdmin->Init();

		LOGD("Loading settings...");
		m_GroupManager    = new cGroupManager();
		m_CraftingRecipes = new cCraftingRecipes;
		m_FurnaceRecipe   = new cFurnaceRecipe();
		
		LOGD("Loading worlds...");
		LoadWorlds(IniFile);

		LOGD("Loading plugin manager...");
		m_PluginManager = new cPluginManager();
		m_PluginManager->ReloadPluginsNow(IniFile);
		
		LOGD("Loading MonsterConfig...");
		m_MonsterConfig = new cMonsterConfig;

		// This sets stuff in motion
		LOGD("Starting Authenticator...");
		m_Authenticator.Start(IniFile);
		
		IniFile.WriteFile("settings.ini");

		LOGD("Starting worlds...");
		StartWorlds();
		
		LOGD("Starting deadlock detector...");
		dd.Start();
		
		LOGD("Finalising startup...");
		m_Server->Start();
		
		m_WebAdmin->Start();

		#if !defined(ANDROID_NDK)
		LOGD("Starting InputThread...");
		m_InputThread = new cThread( InputThread, this, "cRoot::InputThread" );
		m_InputThread->Start( false );	// We should NOT wait? Otherwise we can´t stop the server from other threads than the input thread
		#endif

		long long finishmseconds = Time.GetNowTime();
		finishmseconds -= mseconds;

		LOG("Startup complete, took %i ms!", finishmseconds);

		while (!m_bStop && !m_bRestart)  // These are modified by external threads
		{
			cSleep::MilliSleep(1000);
		}

		#if !defined(ANDROID_NDK)
		delete m_InputThread; m_InputThread = NULL;
		#endif

		// Deallocate stuffs
		LOG("Shutting down server...");
		m_Server->Shutdown();
		
		LOGD("Shutting down deadlock detector...");
		dd.Stop();
		
		LOGD("Stopping world threads...");
		StopWorlds();
		
		LOGD("Stopping authenticator...");
		m_Authenticator.Stop();

		LOGD("Freeing MonsterConfig...");
		delete m_MonsterConfig; m_MonsterConfig = NULL;
		delete m_WebAdmin; m_WebAdmin = NULL;
		LOGD("Unloading recipes...");
		delete m_FurnaceRecipe;   m_FurnaceRecipe = NULL;
		delete m_CraftingRecipes; m_CraftingRecipes = NULL;
		LOGD("Forgetting groups...");
		delete m_GroupManager; m_GroupManager = 0;
		LOGD("Unloading worlds...");
		UnloadWorlds();
		
		LOGD("Stopping plugin manager...");
		delete m_PluginManager; m_PluginManager = NULL;

		cItemHandler::Deinit();
		cBlockHandler::Deinit();

		LOG("Cleaning up...");
		//delete HeartBeat; HeartBeat = 0;
		delete m_Server; m_Server = 0;
		LOG("Shutdown successful!");
	}

	delete m_Log; m_Log = 0;
}
Beispiel #11
0
void task_service_t::exec_task(thread_t* thd_)
{
    deque<async_method_t> tasks;
    uint32_t all_task_num = 0;
    uint32_t thread_num = m_thread_group.size();

    if (NULL == thd_)
    {
        LOGWARN((TASK_SERVICE_MODULE, "task_service_t::exec_task service(%s) thread is NULL, return", m_service_name.c_str()));
        return;
    }

    if (!thread_num)
    {
        LOGWARN((TASK_SERVICE_MODULE, "task_service_t::exec_task service(%s) thread_num equals zero, return", m_service_name.c_str()));
        return;
    }

    while (!m_stop_signal || !m_task_queue.empty())
    {
        struct timeval cached_now;
        //! yunjie: prepare the task buffer
        tasks.clear();

        while (1)
        {
            //! yunjie: 处理定时事件
            m_timer_manager.flush_time();
            cached_now = m_timer_manager.get_cached_time();

            //! yunjie: 如果有timer时间超时, 将会在函数内部执行callback
            m_timer_manager.exec();

            //! yunjie; 进行网络IO检测, 并会调用相应 读/写 回调
            int wake_num = m_io_handler.wait_io_notification();

            //! yunjie: 本来是采用动态调整m_fetch_num_per_loop来平衡每个线程的任务抓取量, 发现并没有太大意义, 改为一次性全部获取所有任务
            m_task_queue.fetch_task(tasks, all_task_num, m_fetch_num_per_loop);
            if (wake_num || tasks.size() || m_stop_signal)      //! yunjie: 需要判断m_stop_signal, 否则外部投递stop信号号会发生join永远阻塞
            {
                break;
            }

#if USE_COND_VAR
            thd_->cond_wait(cached_now, 0, TIMEDOUT_US);
#else
            thread_t::usleep(TIMEDOUT_US);
#endif
        }

        //! yunjie: calc the fetch_num_per_loop
        if (thread_num != 1)
        {
            m_fetch_num_per_loop = all_task_num / thread_num;
            if (!m_fetch_num_per_loop)
            {
                m_fetch_num_per_loop = MIN_TASK_FETCH_NUM;
            }

            if (m_fetch_num_per_loop > MAX_TASK_FETCH_NUM)
            {
                m_fetch_num_per_loop = MAX_TASK_FETCH_NUM;
            }
        }

        //! yunjie: 处理异步请求
        for (deque<async_method_t>::iterator it = tasks.begin(); it != tasks.end(); ++it)
        {
            (*it)();
            it->release();
        }
    }

    m_timer_manager.clear();

    assert(0 == m_task_queue.size());

}
Beispiel #12
0
int cLuaState::CallFunctionWithForeignParams(
	const AString & a_FunctionName,
	cLuaState & a_SrcLuaState,
	int a_SrcParamStart,
	int a_SrcParamEnd
)
{
	ASSERT(IsValid());
	ASSERT(a_SrcLuaState.IsValid());
	
	// Store the stack position before any changes
	int OldTop = lua_gettop(m_LuaState);
	
	// Push the function to call, including the error handler:
	if (!PushFunction(a_FunctionName.c_str()))
	{
		LOGWARNING("Function '%s' not found", a_FunctionName.c_str());
		lua_pop(m_LuaState, 2);
		return -1;
	}

	// Copy the function parameters to the target state
	if (CopyStackFrom(a_SrcLuaState, a_SrcParamStart, a_SrcParamEnd) < 0)
	{
		// Something went wrong, fix the stack and exit
		lua_pop(m_LuaState, 2);
		m_NumCurrentFunctionArgs = -1;
		m_CurrentFunctionName.clear();
		return -1;
	}
	
	// Call the function, with an error handler:
	int s = lua_pcall(m_LuaState, a_SrcParamEnd - a_SrcParamStart + 1, LUA_MULTRET, OldTop + 1);
	if (ReportErrors(s))
	{
		LOGWARN("Error while calling function '%s' in '%s'", a_FunctionName.c_str(), m_SubsystemName.c_str());
		// Fix the stack.
		// We don't know how many values have been pushed, so just get rid of any that weren't there initially
		int CurTop = lua_gettop(m_LuaState);
		if (CurTop > OldTop)
		{
			lua_pop(m_LuaState, CurTop - OldTop);
		}
		
		// Reset the internal checking mechanisms:
		m_NumCurrentFunctionArgs = -1;
		m_CurrentFunctionName.clear();
		
		// Make Lua think everything is okay and return 0 values, so that plugins continue executing.
		// The failure is indicated by the zero return values.
		return 0;
	}
	
	// Reset the internal checking mechanisms:
	m_NumCurrentFunctionArgs = -1;
	m_CurrentFunctionName.clear();
	
	// Remove the error handler from the stack:
	lua_remove(m_LuaState, OldTop + 1);
	
	// Return the number of return values:
	return lua_gettop(m_LuaState) - OldTop;
}
Beispiel #13
0
void serialport_set_baudrate(unsigned int baudrate)
{
    switch(baudrate)
    {
        case 2400:
            cfsetispeed(&term,B2400);
            cfsetospeed(&term,B2400);
            break;
            
        case 4800:
            cfsetispeed(&term,B4800);
            cfsetospeed(&term,B4800);
            break;
            
        case 9600:
            cfsetispeed(&term,B9600);
            cfsetospeed(&term,B9600);
            break;
            
        case 19200:
            cfsetispeed(&term,B19200);
            cfsetospeed(&term,B19200);
            break;
            
        case 38400:
            cfsetispeed(&term,B38400);
            cfsetospeed(&term,B38400);
            break;
            
        case 57600:
            cfsetispeed(&term,B57600);
            cfsetospeed(&term,B57600);
            break;
            
        case 115200:
            cfsetispeed(&term,B115200);
            cfsetospeed(&term,B115200);
            break;
            
        case 230400:
            cfsetispeed(&term,B230400);
            cfsetospeed(&term,B230400);
            break;
#ifndef __APPLE__
        case 460800:
            cfsetispeed(&term,B460800);
            cfsetospeed(&term,B460800);
            break;
            
        case 921600:
            cfsetispeed(&term,B921600);
            cfsetospeed(&term,B921600);
            break;
#endif
        default:
            LOGWARN("serialport_set_baudrate: baud rate %d may not work", baudrate);
            cfsetispeed(&term,baudrate);
            cfsetospeed(&term,baudrate);
            break;
    }
}
Beispiel #14
0
/// Creates the underlying O/S file handle.
///
/// @param[in] pszName name of the pipe
/// @param[in] bServer true if this is a server end, false if it is a client
/// @param[in] bExclusive false if this is a pipe that can be shared by multiple clients or servers
/// @param[in] bReader true if this is the reading end of a pipe, false if it is the writing end
/// @return the O/S file handle
static CTimeoutIO::FILE_REFERENCE _CreatePipe (const TCHAR *pszName, bool bServer, bool bExclusive, bool bReader) {
#ifdef _WIN32
	HANDLE handle;
	if (bServer) {
		SECURITY_DESCRIPTOR sd;
		SECURITY_ATTRIBUTES sa;
		InitializeSecurityDescriptor (&sd, SECURITY_DESCRIPTOR_REVISION);
		// TODO [PLAT-1119] Get a SDDL from the registry for the DACL (and pass it into this library)
		SetSecurityDescriptorDacl (&sd, TRUE, NULL, FALSE);
		ZeroMemory (&sa, sizeof (sa));
		sa.nLength = sizeof (sa);
		sa.lpSecurityDescriptor = &sd;
		sa.bInheritHandle = FALSE;
		handle = CreateNamedPipe (
			pszName,
			(bReader ? PIPE_ACCESS_INBOUND : PIPE_ACCESS_OUTBOUND) | (bExclusive ? FILE_FLAG_FIRST_PIPE_INSTANCE : 0) | FILE_FLAG_OVERLAPPED,
			(bExclusive ? PIPE_TYPE_BYTE | PIPE_READMODE_BYTE : PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE) | PIPE_WAIT | PIPE_REJECT_REMOTE_CLIENTS,
			bExclusive ? 1 : PIPE_UNLIMITED_INSTANCES,
			0,
			0,
			0,
			&sa);
	} else {
		// TODO: share or exclusive? We want a 1:1 on the pipe we've connected to - the server will open another for new clients
		handle = CreateFile (pszName, bReader ? GENERIC_READ : GENERIC_WRITE, 0/* bReader ? FILE_SHARE_READ : FILE_SHARE_WRITE */, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
	}
	if (handle == INVALID_HANDLE_VALUE) {
		DWORD dwError = GetLastError ();
		LOGWARN (TEXT ("Couldn't create pipe ") << pszName << TEXT(", error ") << dwError);
		SetLastError (dwError);
		return NULL;
	}
	LOGINFO (TEXT ("Created pipe ") << pszName);
	return handle;
#else /* ifdef _WIN32 */
	if (bExclusive) {
		if (mkfifo (pszName, 0666)) {
			int ec = GetLastError ();
			LOGWARN (TEXT ("Couldn't create pipe ") << pszName << TEXT (", error ") << ec);
			SetLastError (ec);
			return 0;
		}
		CThread *poOpener = new CNamedPipeOpenThread (pszName, bReader ? O_WRONLY : O_RDONLY);
		poOpener->Start ();
		CThread::Release (poOpener);
		int file = open (pszName, bReader ? O_RDONLY : O_WRONLY);
		if (file <= 0) {
			int ec = GetLastError ();
			LOGWARN (TEXT ("Couldn't open pipe ") << pszName << TEXT (", error ") << ec);
			if (unlink (pszName)) {
				LOGWARN (TEXT ("Couldn't delete pipe ") << pszName << TEXT (", error ") << GetLastError ());
			}
			SetLastError (ec);
			return 0;
		}
		LOGINFO (TEXT ("Created pipe ") << pszName);
		return file;
	} else {
		int sock;
		sock = socket (AF_UNIX, SOCK_STREAM, 0);
		if (sock < 0) {
			int ec = GetLastError ();
			LOGWARN (TEXT ("Couldn't open pipe ") << pszName << TEXT (", error ") << ec);
			SetLastError (ec);
			return 0;
		}
		if (!_SetDefaultSocketOptions (sock)) {
			int ec = GetLastError ();
			close (sock);
			LOGWARN (TEXT ("Couldn't set default options ") << pszName << TEXT (", error ") << ec);
			SetLastError (ec);
			return 0;
		}
		struct sockaddr_un addr;
		addr.sun_family = AF_UNIX;
		StringCbPrintf (addr.sun_path, sizeof (addr.sun_path), TEXT ("%s"), pszName);
		if (bServer) {
			if (!unlink (pszName)) {
				LOGINFO (TEXT ("Deleted previous instance of ") << pszName);
			}
			if (bind (sock, (struct sockaddr*)&addr, sizeof (addr.sun_family) + _tcslen (addr.sun_path))) {
				int ec = GetLastError ();
				close (sock);
				LOGWARN (TEXT ("Couldn't open pipe ") << pszName << TEXT (", error ") << ec);
				SetLastError (ec);
				return 0;
			}
			if (fcntl (sock, F_SETFL, O_NONBLOCK) || listen (sock, 0)) {
				int ec = GetLastError ();
				close (sock);
				LOGWARN (TEXT ("Couldn't open pipe ") << pszName << TEXT (", error ") << ec);
				SetLastError (ec);
				return 0;
			}
			LOGINFO (TEXT ("Created server Unix Domain Socket ") << pszName);
		} else {
			if (connect (sock, (struct sockaddr*)&addr, sizeof (addr.sun_family) + _tcslen (addr.sun_path))) {
				int ec = GetLastError ();
				close (sock);
				LOGWARN (TEXT ("Couldn't open pipe ") << pszName << TEXT (", error ") << ec);
				switch (ec) {
				case EAGAIN :
					LOGDEBUG (TEXT ("Translating EAGAIN to ENOENT"));
					ec = ENOENT;
					break;
				case ECONNREFUSED :
					LOGDEBUG (TEXT ("Translating ECONNREFUSED to ENOENT"));
					ec = ENOENT;
					break;
				}
				SetLastError (ec);
				return 0;
			}
			LOGDEBUG (TEXT ("Connection accepted, waiting for handshake confirmation"));
			if ((recv (sock, addr.sun_path, 1, 0) != 1) || fcntl (sock, F_SETFL, O_NONBLOCK)) {
				int ec = GetLastError ();
				close (sock);
				LOGWARN (TEXT ("Handshake not received on ") << pszName << TEXT (", error ") << ec);
				switch (ec) {
				case EAGAIN :
					LOGDEBUG (TEXT ("Translating EAGAIN to ENOENT"));
					ec = ENOENT;
					break;
				}
				SetLastError (ec);
				return 0;
			}
			LOGINFO (TEXT ("Connected to Unix Domain Socket ") << pszName);
		}
		return sock;
	}
#endif /* ifdef _WIN32 */
}
Beispiel #15
0
//!
//!
//!
//! @param[in] path
//! @param[in] offset
//! @param[in] lodev name of the loop device
//! @param[in] lodev_size
//!
//! @return EUCA_OK on success or the following error codes:
//!         \li EUCA_ERROR: if any error occured.
//!         \li EUCA_INVALID_ERROR: if any parameter does not meet the preconditions.
//!
//! @pre Both path and lodev parameters must not be NULL.
//!
//! @post On success, the loop device is attached.
//!
int diskutil_loop(const char *path, const long long offset, char *lodev, int lodev_size)
{
    int i = 0;
    int ret = EUCA_OK;
    char *ptr = NULL;
    char *output = NULL;
    boolean done = FALSE;
    boolean found = FALSE;
    boolean do_log = FALSE;

    if (path && lodev) {
        // we retry because we cannot atomically obtain a free loopback device on all distros (some
        // versions of 'losetup' allow a file argument with '-f' options, but some do not)
        for (i = 0, done = FALSE, found = FALSE; i < LOOP_RETRIES; i++) {
            sem_p(loop_sem);
            {
                output = pruntf(TRUE, "%s %s -f", helpers_path[ROOTWRAP], helpers_path[LOSETUP]);
            }
            sem_v(loop_sem);

            if (output == NULL) {
                // there was a problem
                break;
            }

            if (strstr(output, "/dev/loop")) {
                strncpy(lodev, output, lodev_size);
                if ((ptr = strrchr(lodev, '\n')) != NULL) {
                    *ptr = '\0';
                    found = TRUE;
                }
            }

            EUCA_FREE(output);

            if (found) {
                do_log = ((i + 1) == LOOP_RETRIES); // log error on last try only
                LOGDEBUG("attaching file %s\n", path);
                LOGDEBUG("            to %s at offset %lld\n", lodev, offset);
                sem_p(loop_sem);
                {
                    char str_offset[64];
                    snprintf(str_offset, sizeof(str_offset), "%lld", offset);
                    output = execlp_output(do_log, helpers_path[ROOTWRAP], helpers_path[LOSETUP], "-o", str_offset, lodev, path, NULL);
                }
                sem_v(loop_sem);

                if (output == NULL) {
                    LOGDEBUG("cannot attach to loop device %s (will retry)\n", lodev);
                } else {
                    EUCA_FREE(output);
                    done = TRUE;
                    break;
                }
            }

            sleep(1);
            found = FALSE;
        }

        if (!done) {
            LOGERROR("cannot find free loop device or attach to one\n");
            ret = EUCA_ERROR;
        }

        return (ret);
    }

    LOGWARN("cannot attach to loop device. path=%s, lodev=%s\n", SP(path), SP(lodev));
    return (EUCA_INVALID_ERROR);
}
Beispiel #16
0
/// Accepts an incoming connection on a server pipe.
///
/// @param[in] timeout maximum time to wait for a client in milliseconds
/// @return this end of a pipe connected to the client, or NULL if none was available
CNamedPipe *CNamedPipe::Accept (unsigned long timeout) {
	assert (IsServer ());
#ifdef _WIN32
	if (!ConnectNamedPipe (GetFile (), GetOverlapped ())) {
		if (GetLastError () != ERROR_PIPE_CONNECTED) {
			if (!WaitOnOverlapped (timeout)) {
				DWORD dwError = GetLastError ();
				LOGWARN (TEXT ("Overlapped result not available, error ") << dwError);
				SetLastError (dwError);
				return NULL;
			}
		}
	}
	HANDLE handle = _CreatePipe (GetName (), IsServer (), false, IsReader ());
	if (!handle) {
		DWORD dwError = GetLastError ();
		LOGWARN (TEXT ("Couldn't create replacement pipe for server, error ") << dwError);
		SetLastError (dwError);
		return NULL;
	}
	CNamedPipe *poClient = new CNamedPipe (GetFile (), GetName (), false, IsReader ());
	SetFile (handle);
	return poClient;
#else
failedOperation:
	struct sockaddr_un addr;
	bool bLazyWait = false;
	if (IsLazyClosing ()) {
		bLazyWait = true;
		timeout = IsLazyClosing ();
	}
timeoutOperation:
	int sock;
	if (BeginOverlapped (timeout, true)) {
		socklen_t len = sizeof (addr);
		sock = accept (GetFile (), (struct sockaddr*)&addr, &len);
		EndOverlapped ();
	} else {
		sock = -1;
	}
	if (sock < 0) {
		int ec = GetLastError ();
		if (ec == EINTR) {
			LOGDEBUG (TEXT ("Accept interrupted"));
			if (IsLazyClosing ()) {
				if (bLazyWait) {
					LOGINFO (TEXT ("Closing file on idle timeout"));
					Close ();
				}
			}
			if (!IsClosed () && !bLazyWait) {
				bLazyWait = true;
				timeout = IsLazyClosing ();
				LOGDEBUG (TEXT ("Resuming operation with idle timeout of ") << timeout << TEXT ("ms"));
				goto timeoutOperation;
			}
		}
		LOGWARN (TEXT ("Couldn't accept client, error ") << ec);
		SetLastError (ec);
		return NULL;
	}
	LOGINFO (TEXT ("Connection accepted on ") << GetName ());
	if (!_SetDefaultSocketOptions (sock)) {
		int ec = GetLastError ();
		close (sock);
		LOGWARN (TEXT ("Couldn't set default socket options, error ") << ec);
		SetLastError (ec);
		return NULL;
	}
	if ((send (sock, "!", 1, 0) != 1) || fcntl (sock, F_SETFL, O_NONBLOCK)) {
		int ec = GetLastError ();
		close (sock);
		if (ec == EPIPE) {
			LOGWARN (TEXT ("Client disconnected before receiving handshake"));
			goto failedOperation;
		}
		LOGWARN (TEXT ("Couldn't send handshake message, error ") << ec);
		SetLastError (ec);
		return NULL;
	} else {
		LOGDEBUG (TEXT ("Handshake message written"));
	}
	return new CNamedPipe (sock, GetName (), false, IsReader ());
#endif
}
void TskCarveExtractScalpel::carveFile(const std::string &unallocImgPath, const std::string &outputFolderPath, const std::string &stdOutFilePath, const std::string &stdErrFilePath) const
{
    try
    {
        // Find out where Scalpel is installed.
        std::string scalpelDirPath = GetSystemProperty("SCALPEL_DIR");
        if (scalpelDirPath.empty())
        {
            throw TskException("TskCarveExtractScalpel::configure : Scalpel directory not set");
        }

        if (!Poco::File(scalpelDirPath).exists())
        {
            std::stringstream msg;
            msg << "TskCarveExtractScalpel::configure : specified Scalpel directory '" << scalpelDirPath << "' does not exist";
            throw TskException(msg.str());
        }

        // Get the path to the Scalpel executable.
        std::stringstream pathBuilder;
        pathBuilder << scalpelDirPath << Poco::Path::separator() << SCALPEL_EXE_FILE_NAME;
        std::string scalpelExePath = pathBuilder.str();
        if (!Poco::File(scalpelExePath).exists())
        {
            std::stringstream msg;
            msg << "TskCarveExtractScalpel::configure : Scalpel executable '" << scalpelExePath << "' does not exist";
            throw TskException(msg.str());
        }

        // Get the path to the Scalpel config file.
        std::string scalpelConfigFilePath = GetSystemProperty("SCALPEL_CONFIG_FILE");
        if (!Poco::File(scalpelConfigFilePath).exists())
        {
            std::stringstream msg;
            msg << "TskCarveExtractScalpel::TskCarveExtractScalpel : Scalpel config file '" << scalpelConfigFilePath << "' does not exist";
            throw TskException(msg.str());
        }

        // Set the Scalpel command line: specify the Scalpel config file.
        Poco::Process::Args args;
        args.push_back("-c");
        args.push_back(scalpelConfigFilePath);

        // Set the Scalpel command line: allow for nested headers and footers.
        args.push_back("-e");
        
        // Set the Scalpel command line: put any carved files directly into the output folder.
        args.push_back("-o");
        args.push_back(outputFolderPath);
        args.push_back("-O");

        // Set the Scalpel command line: specify the file to carve.
        args.push_back(unallocImgPath);

        // Launch Scalpel with console output redirects.
        Poco::Pipe outPipe;
        Poco::Pipe errPipe;
        Poco::ProcessHandle handle = Poco::Process::launch(scalpelExePath, args, NULL, &outPipe, &errPipe);

        // Capture the console output. Note that Scalpel may block at times as it waits for this loop to empty the stream buffers.
        Poco::PipeInputStream stdOutInputStream(outPipe);
        Poco::FileOutputStream stdOutOutputStream(stdOutFilePath);
        Poco::PipeInputStream stdErrInputStream(errPipe);
        Poco::FileOutputStream stdErrOutputStream(stdErrFilePath);
        while (stdOutInputStream || stdErrInputStream)
        {
            if (stdOutInputStream)
            {
                Poco::StreamCopier::copyStream(stdOutInputStream, stdOutOutputStream);
            }

            if (stdErrInputStream)
            {
                Poco::StreamCopier::copyStream(stdErrInputStream, stdErrOutputStream);
            }
        }
    
        // Scalpel should be finished since the console output streams are closed.
        int exitCode = Poco::Process::wait(handle);

        stdOutOutputStream.flush();
        stdErrOutputStream.flush();

        // On the first invocation of Scalpel, record its use in the image database.
        static bool toolInfoRecorded = false;
        if (!toolInfoRecorded)
        {
            std::ifstream stdOutStream(stdOutFilePath.c_str());
            if (stdOutStream)
            {
                std::string versionString;
                std::getline(stdOutStream, versionString);
                Poco::StringTokenizer tokenizer(versionString, "\t ", Poco::StringTokenizer::TOK_IGNORE_EMPTY | Poco::StringTokenizer::TOK_TRIM); 
                if (tokenizer[0] == "Scalpel" && tokenizer[1] == "version")
                {
                    TskServices::Instance().getImgDB().addToolInfo("Scalpel", tokenizer[2].c_str());
                    toolInfoRecorded = true;
                }
                else
                {
                    LOGWARN("TskCarveExtractScalpel::carveFile : Scalpel stdout output format changed, cannot record tool info");
                }
            }
            else
            {
                LOGWARN("TskCarveExtractScalpel::carveFile : failed to open stdout stream, cannot record tool info");
            }
        }

        // Delete input files by default.
        std::string option = GetSystemProperty("CARVE_EXTRACT_KEEP_INPUT_FILES");
        std::transform(option.begin(), option.end(), option.begin(), ::toupper);
        bool deleteInputFiles = (option != "TRUE");

        if (deleteInputFiles)
        {
            Poco::File file(unallocImgPath);
            file.remove();
        }

        if (exitCode != 0)
        {
            std::stringstream msg;
            msg << "TskCarveExtractScalpel::carveFile : Scalpel exited with error exit code " << exitCode << " when carving '" << unallocImgPath.c_str() << "'";
            throw TskException(msg.str());
        }
    }
    catch (Poco::Exception &ex)
    {
        std::stringstream msg;
        msg << "TskCarveExtractScalpel::carveFile : Poco exception: " << ex.displayText();
        throw TskException(msg.str());
    }
}