Пример #1
0
// read the entire file into a ConfigVar instance and then use that to decode
// into mapped variables.
bool ConfigReader::load(const char *fileName) {
  struct stat stbuf;
  memset(&stbuf, 0, sizeof(struct stat));
  if (lstat(fileName, &stbuf) != 0) return false;

  int size = stbuf.st_size;

  int fd = open(fileName, O_RDONLY);
  if (fd < 0) return false;

  char *buf = new char[size];

  int res = ::read(fd, buf, size);
  close(fd);

  if (res != size) {
    RLOG(WARNING) << "Partial read of config file, expecting " << size
                  << " bytes, got " << res;
    delete[] buf;
    return false;
  }

  ConfigVar in;
  in.write((unsigned char *)buf, size);
  delete[] buf;

  return loadFromVar(in);
}
Пример #2
0
// read the entire file into a ConfigVar instance and then use that to decode
// into mapped variables.
bool ConfigReader::load(const char *fileName) {
  struct stat_st stbuf;
  memset(&stbuf, 0, sizeof(struct stat_st));
  if (unix::lstat(fileName, &stbuf) != 0) return false;

  int size = stbuf.st_size;

  int fd = unix::open(fileName, O_RDONLY);
  if (fd < 0) return false;

  char *buf = new char[size];

  int res = ::_read(fd, buf, size);
  close(fd);

  if (res != size) {
    rWarning("Partial read of config file, expecting %i bytes, got %i", size,
             res);
    delete[] buf;
    return false;
  }

  ConfigVar in;
  in.write((unsigned char *)buf, size);
  delete[] buf;

  return loadFromVar(in);
}
Пример #3
0
bool Config::Init(const char* filename_)
{
    FILE*       fp;
    char        buffer[1024];
    char        token[1024];
    char        name[1024];
    char*       p;
    int         nline;
    ConfigVar*  var;
    
    filename = filename_;
    fp = fopen(filename, "r");
    if (!fp)
        return false;
    
    nline = 0;
    while (fgets(buffer, sizeof(buffer) - 1, fp))
    {
        buffer[sizeof(buffer) - 1] = '\0';
        nline++;
        p = ParseToken(buffer, token, sizeof(token));
        if (!p)
        {
            // empty or commented line
            continue;
        }
        
        strncpy(name, token, strlen(token));
        name[strlen(token)] = '\0';
        
        p = ParseToken(p, token, sizeof(token));
        if (!p || token[0] != '=')
        {
            // syntax error
            Log_Message("syntax error at %s, line %d", filename, nline);
            fclose(fp);
            return false;
        }
        
        var = new ConfigVar(name);
        vars.Enqueue(var);
        while (true)
        {
            p = ParseToken(p, token, sizeof(token));
            if (!p)
                break;
            if (token[0] == ',')
                continue;

            var->Append(token);
        }
    }
    
    fclose(fp);
    return true;
}
Пример #4
0
const char* Config::GetListValue(const char* name, int num, const char* defval)
{
    ConfigVar* var;
    
    var = GetVar(name);
    if (!var)
        return defval;
    
    return var->GetListValue(num, defval);
}
Пример #5
0
int64_t Config::GetInt64Value(const char* name, int64_t defval)
{
    ConfigVar* var;
    
    var = GetVar(name);
    if (!var)
        return defval;
    
    return var->GetInt64Value(defval);
}
Пример #6
0
bool Config::GetBoolValue(const char* name, bool defval)
{
    ConfigVar* var;
    
    var = GetVar(name);
    if (!var)
        return defval;
    
    return var->GetBoolValue(defval);
}
Пример #7
0
int Config::GetListNum(const char* name)
{
    ConfigVar* var;
    
    var = GetVar(name);
    if (!var)
        return 0;

    return var->GetListNum();
}
Пример #8
0
// take in a DM plugin configuration file, find the DMPlugin descendent matching the value of plugname, and store its class factory funcs for later use
DMPlugin* dm_plugin_load(const char *pluginConfigPath)
{
	ConfigVar cv;

	if (cv.readVar(pluginConfigPath, "=") > 0) {
		if (!is_daemonised) {
			std::cerr << "Unable to load plugin config: " << pluginConfigPath << std::endl;
		}
		syslog(LOG_ERR, "Unable to load plugin config %s", pluginConfigPath);
		return NULL;
	}

	String plugname(cv["plugname"]);

	if (plugname.length() < 1) {
		if (!is_daemonised) {
			std::cerr << "Unable read plugin config plugname variable: " << pluginConfigPath << std::endl;
		}
		syslog(LOG_ERR, "Unable read plugin config plugname variable %s", pluginConfigPath);
		return NULL;
	}

	if (plugname == "default") {
#ifdef DGDEBUG
		std::cout << "Enabling default DM plugin" << std::endl;
#endif
		return defaultdmcreate(cv);
	}
	
#ifdef ENABLE_FANCYDM
	if (plugname == "fancy") {
#ifdef DGDEBUG
		std::cout << "Enabling fancy DM plugin" << std::endl;
#endif
		return fancydmcreate(cv);
	}
#endif

#ifdef ENABLE_TRICKLEDM
	if (plugname == "trickle") {
#ifdef DGDEBUG
		std::cout << "Enabling trickle DM plugin" << std::endl;
#endif
		return trickledmcreate(cv);
	}
#endif

	if (!is_daemonised) {
		std::cerr << "Unable to load plugin: " << plugname << std::endl;
	}
	syslog(LOG_ERR, "Unable to load plugin %s", plugname.toCharArray());
	return NULL;
}
Пример #9
0
void Config::AppendListValue(const char* name, const char* value)
{
    ConfigVar*  var;

    var = GetVar(name);
    if (!var)
    {
        var = new ConfigVar(name);
        vars.Enqueue(var);
    }

    var->Append(value);
}
Пример #10
0
void Config::SetValue(const char* name, const char *value)
{
    ConfigVar*  var;

    var = GetVar(name);
    if (!var)
    {
        var = new ConfigVar(name);
        vars.Enqueue(var);
    }
    else
        var->ClearValue();

    var->Append(value);
}
Пример #11
0
ConfigVar* Config::GetVar(const char* name)
{
    ConfigVar* var;
    
    var = vars.First();
    while (var)
    {
        if (var->NameEquals(name))
            return var;
        
        var = var->next;
    }
    
    return NULL;
}
Пример #12
0
//------------------------------------------------------------------------------
void
Background2D::renderQueueEnded( Ogre::uint8 queueGroupId, const Ogre::String& invocation, bool& repeatThisInvocation )
{
    if( cv_show_background2d.GetB() == false )
    {
        return;
    }



    if( queueGroupId == Ogre::RENDER_QUEUE_MAIN )
    {
        m_RenderSystem->_setWorldMatrix( Ogre::Matrix4::IDENTITY );
        m_RenderSystem->_setProjectionMatrix( Ogre::Matrix4::IDENTITY );

        Ogre::Viewport *viewport( CameraManager::getSingleton().getViewport() );
        float width = viewport->getActualWidth();
        float height = viewport->getActualHeight();
        Ogre::Matrix4 view;
        view.makeTrans( Ogre::Vector3( m_PositionReal.x * 2 / width, -m_PositionReal.y * 2 / height, 0 ) );
        m_RenderSystem->_setViewMatrix( view );

        if( m_AlphaRenderOp.vertexData->vertexCount != 0 )
        {
            m_SceneManager->_setPass( m_AlphaMaterial->getTechnique( 0 )->getPass( 0 ), true, false );
            m_RenderSystem->_render( m_AlphaRenderOp );
        }

        if( m_AddRenderOp.vertexData->vertexCount != 0 )
        {
            m_SceneManager->_setPass( m_AddMaterial->getTechnique( 0 )->getPass( 0 ), true, false );
            m_RenderSystem->_render( m_AddRenderOp );
        }
    }
}
Пример #13
0
static bool
runTest(TestListener *listener, const std::string &suite,
             const std::string &testName, TestDg test)
{
    if (listener)
        listener->testStarted(suite, testName);

    bool protect = !isDebuggerAttached();
    protect = protect || g_protect->val();
    if (protect) {
        try {
            test();
            if (listener)
                listener->testComplete(suite, testName);
        } catch (const Assertion &assertion) {
            if (listener)
                listener->testAsserted(suite, testName, assertion);
            return false;
        } catch (...) {
            if (listener)
                listener->testException(suite, testName);
            return false;
        }
    } else {
        test();
        if (listener)
            listener->testComplete(suite, testName);
    }
    return true;
}
Пример #14
0
//------------------------------------------------------------------------------
void
Background2D::InputDebug( const Event& event )
{
    if( cv_background2d_manual.GetB() == true )
    {
        if( event.type == ET_KEY_IMPULSE && event.param1 == OIS::KC_W )
        {
            m_PositionReal.y += 2;
        }
        else if( event.type == ET_KEY_IMPULSE && event.param1 == OIS::KC_A )
        {
            m_PositionReal.x += 2;
        }
        else if( event.type == ET_KEY_IMPULSE && event.param1 == OIS::KC_S )
        {
            m_PositionReal.y -= 2;
        }
        else if( event.type == ET_KEY_IMPULSE && event.param1 == OIS::KC_D )
        {
            m_PositionReal.x -= 2;
        }

        CameraManager::getSingleton().Set2DScroll( m_PositionReal );
    }
}
Пример #15
0
BufferedStream::BufferedStream(Stream::ptr parent, bool own)
: FilterStream(parent, own)
{
    m_bufferSize = g_defaultBufferSize->val();
    m_allowPartialReads = false;
    m_flushMultiplesOfBuffer = false;
}
Пример #16
0
TempStream::TempStream(const std::string &prefix, bool deleteOnClose,
                       IOManager *ioManager, Scheduler *scheduler)
{
    std::string tempdir;
    bool absolutePath =
#ifdef WINDOWS
        (prefix.size() >= 2 && (prefix[1] == ':' || prefix[1] == '\\')) ||
        (!prefix.empty() && prefix[0] == '\\');
#else
        !prefix.empty() && prefix[0] == '/';
#endif
    if (!absolutePath)
        tempdir = g_tempDir->val();
#ifdef WINDOWS
    std::wstring wtempdir = toUtf16(tempdir);
    if (!absolutePath && wtempdir.empty()) {
        wtempdir.resize(MAX_PATH);
        DWORD len = GetTempPathW(MAX_PATH, &wtempdir[0]);
        if (len == 0)
            wtempdir = L".";
        else
            wtempdir.resize(len);
    }
    std::wstring prefixW = toUtf16(prefix);
    size_t backslash = prefixW.rfind(L'\\');
    if (backslash != std::wstring::npos) {
        wtempdir += prefixW.substr(0, backslash);
        prefixW = prefixW.substr(backslash + 1);
    }
    std::wstring tempfile;
    tempfile.resize(MAX_PATH);
    UINT len = GetTempFileNameW(wtempdir.c_str(),
        prefixW.c_str(),
        0,
        &tempfile[0]);
    if (len == 0)
        MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("GetTempFileNameW");
    init(tempfile, FileStream::READWRITE,
        (FileStream::CreateFlags)(FileStream::OPEN |
            (deleteOnClose ? FileStream::DELETE_ON_CLOSE : 0)),
        ioManager, scheduler);
#else
    if (!absolutePath && tempdir.empty())
        tempdir = "/tmp/" + prefix + "XXXXXX";
    else if (!absolutePath)
        tempdir += prefix + "XXXXXX";
    else
        tempdir = prefix + "XXXXXX";
    int fd = mkstemp(&tempdir[0]);
    if (fd < 0)
        MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("mkstemp");
    init(fd, ioManager, scheduler);
    if (deleteOnClose) {
        int rc = unlink(tempdir.c_str());
        if (rc != 0)
            MORDOR_THROW_EXCEPTION_FROM_LAST_ERROR_API("unlink");
    }
    m_path = tempdir;
#endif
}
Пример #17
0
void prefs_set_config_val_real (char *key, char *value, gboolean callback)
{
	ConfigVar *entry = prefs_config_vars;
	while (entry->key)
	{
		if (strcasecmp (entry->key, key) == 0)
		{
			// NOTE: here the old value should not be freed because it is static
			entry->cur_val = g_strdup (value);
			if (callback && entry->callback)
				entry->callback (key, value);
			return;
		}
		entry++;
	}
	fprintf (stderr, "Warning: invalid key %s in config file\n", key);
}
Пример #18
0
//------------------------------------------------------------------------------
void
Background2D::applyScroll()
{
    if( cv_background2d_manual.GetB() != true )
    {
        m_PositionReal = GetScreenScroll();
        CameraManager::getSingleton().Set2DScroll( m_PositionReal );
    }
}
Пример #19
0
bool ConfigReader::save(const char *fileName) const {
  // write everything to a ConfigVar, then output to disk
  ConfigVar out = toVar();

  int fd = unix::open(fileName, O_RDWR | O_CREAT, 0640);
  if (fd >= 0) {
    int retVal = ::write(fd, out.buffer(), out.size());
    close(fd);
    if (retVal != out.size()) {
      rError("Error writing to config file %s", fileName);
      return false;
    }
  } else {
    rError("Unable to open or create file %s", fileName);
    return false;
  }

  return true;
}
Пример #20
0
bool ConfigReader::loadFromVar(ConfigVar &in) {
  in.resetOffset();

  // parse.
  int numEntries = in.readInt();

  for (int i = 0; i < numEntries; ++i) {
    string key, value;
    in >> key >> value;

    if (key.length() == 0) {
      rError("Invalid key encoding in buffer");
      return false;
    }
    ConfigVar newVar(value);
    vars.insert(make_pair(key, newVar));
  }

  return true;
}
Пример #21
0
bool
GameFrameListener::frameEnded( const Ogre::FrameEvent& evt )
{
    if( cv_debug_fps.GetB() == true )
    {
        const Ogre::RenderTarget::FrameStats& stats = m_Window->getStatistics();
        DEBUG_DRAW.SetTextAlignment( DEBUG_DRAW.LEFT );
        DEBUG_DRAW.SetScreenSpace( true );
        DEBUG_DRAW.SetColour( Ogre::ColourValue( 1, 1, 1, 1 ) );
        DEBUG_DRAW.Text( 10, 10, "Current FPS:" + Ogre::StringConverter::toString( stats.lastFPS ) );
    }

    return true;
}
Пример #22
0
bool Config::Save()
{
    FILE*       fp;
    ConfigVar*  var;
    
    
    fp = fopen(filename, "w");
    if (!fp)
        return false;
    
    fprintf(fp, "# Automatically generated configuration file. DO NOT EDIT!\n\n");
    
    for (var = vars.First(); var != NULL; var = var->next)
    {
        fprintf(fp, "%s = \"%s", var->name.GetBuffer(), var->GetListValue(0, ""));
        for (int i = 1; i < var->numelem; i++)
            fprintf(fp, "\",\"%s", var->GetListValue(i, ""));

        fprintf(fp, "\"\n");
    }
    
    fclose(fp);
    return true;
}
Пример #23
0
bool
TimerManager::detectClockRollover(unsigned long long nowUs)
{
    // If the time jumps backward, expire timers (rather than have them
    // expire in the distant future or not at all).
    // We check this way because now() will not roll from 0xffff... to zero
    // since the underlying hardware counter doesn't count microseconds.
    // Use a threshold value so we don't overreact to minor clock jitter.
    bool rollover = false;
    if (nowUs < m_previousTime && // check first in case the next line would underflow
        nowUs < m_previousTime - g_clockRolloverThreshold->val())
    {
        MORDOR_LOG_ERROR(g_log) << this << " clock has rolled back from "
            << m_previousTime << " to " << nowUs << "; expiring all timers";
        rollover = true;
    }
    m_previousTime = nowUs;
    return rollover;
}
Пример #24
0
ConfigVar ConfigReader::toVar() const {
  // write everything to a ConfigVar, then output to disk
  ConfigVar out;
  out.writeInt(vars.size());
  map<string, ConfigVar>::const_iterator it;
  for (it = vars.begin(); it != vars.end(); ++it) {
    out.writeInt(it->first.size());
    out.write((unsigned char *)it->first.data(), it->first.size());
    out.writeInt(it->second.size());
    out.write((unsigned char *)it->second.buffer(), it->second.size());
  }

  return out;
}
Пример #25
0
//------------------------------------------------------------------------------
void
Background2D::UpdateDebug()
{
    // is this necessary? does it cost to apply camera 2d Scroll?
    // if so maybe move this check to applyScroll
    if( m_PositionReal != GetScreenScroll() )
    {
        applyScroll();
    }

    if( cv_debug_background2d.GetB() == true )
    {
        DEBUG_DRAW.SetTextAlignment( DEBUG_DRAW.LEFT );
        DEBUG_DRAW.SetScreenSpace( true );
        DEBUG_DRAW.SetColour( Ogre::ColourValue( 0.0, 0.8, 0.8, 1 ) );
        for( unsigned int i = 0; i < m_AnimationPlayed.size(); ++i )
        {
            DEBUG_DRAW.Text( 150, 34 + i * 12, "Background 2D animation: " + m_AnimationPlayed[ i ].name );
        }
    }
}
Пример #26
0
static bool
runTests(const TestSuites *suites, TestListener *listener)
{
    Assertion::throwOnAssertion = true;
    if (g_wait->val()) {
        while (!isDebuggerAttached())
            sleep(10000ull);
        debugBreak();
    }
    bool result = true;
    if (!suites) suites = g_allTests;
    if (suites) {
        for (TestSuites::const_iterator it(suites->begin());
            it != suites->end();
            ++it) {
            for (TestSuite::second_type::const_iterator
                    it2(it->second.second.begin());
                it2 != it->second.second.end();
                ++it2) {
                if (it->second.first) {
                    result = result && runTest(listener, it->first,
                        "<invariant>", it->second.first);
                }
                result = runTest(listener, it->first, it2->first,
                    it2->second) && result;
            }
            if (it->second.first) {
                result = runTest(listener, it->first,
                    "<invariant>", it->second.first) && result;
            }
        }
    }
    if (listener)
        listener->testsComplete();
    return result;
}
Пример #27
0
void
Entity::UpdateDebug()
{
    int debug = cv_debug_entity.GetI();

    m_DirectionNode->setVisible( debug > 0 );
    m_SolidCollisionNode->setVisible( debug > 0 && m_Solid );
    m_TalkCollisionNode->setVisible( debug > 0 && m_Talkable );

    // debug output
    if( debug > 0 )
    {
        DEBUG_DRAW.SetColour( Ogre::ColourValue::White );
        DEBUG_DRAW.SetScreenSpace( true );
        DEBUG_DRAW.SetTextAlignment( DEBUG_DRAW.CENTER );
        DEBUG_DRAW.SetFadeDistance( 40, 50 );

        Ogre::Vector3 entity_pos = GetPosition();

        DEBUG_DRAW.Text( entity_pos, 0, 0, m_Name );
        DEBUG_DRAW.Text( entity_pos, 0, 12, m_AnimationCurrentName );

        if( debug > 1 )
        {
            static Ogre::String move_state_string[] = { "NONE", "WALKMESH", "LINEAR", "JUMP" };

            DEBUG_DRAW.Text( entity_pos, 0, 24, Ogre::StringConverter::toString( entity_pos ) );
            DEBUG_DRAW.Text( entity_pos, 0, 36, "Triangle: " + Ogre::StringConverter::toString( m_MoveTriangleId ) );
            DEBUG_DRAW.Text( entity_pos, 0, 48, "Move state: " + move_state_string[ m_State ] );
            switch( m_State )
            {
                case Entity::WALKMESH:
                {
                    DEBUG_DRAW.Line3d( entity_pos, m_MovePosition );
                }
                break;

                case Entity::LINEAR:
                {
                    DEBUG_DRAW.Text( m_LinearStart, 0, 0, "Start: " + Ogre::StringConverter::toString( m_LinearStart ) );
                    DEBUG_DRAW.Text( m_LinearEnd, 0, 0, "End: " + Ogre::StringConverter::toString( m_LinearEnd ) );
                    DEBUG_DRAW.Line3d( m_LinearStart, m_LinearEnd );
                }
                break;

                case Entity::JUMP:
                {
                    DEBUG_DRAW.Text( m_JumpStart, 0, 0, "Start: " + Ogre::StringConverter::toString( m_JumpStart ) );
                    DEBUG_DRAW.Text( m_JumpEnd, 0, 0, "End: " + Ogre::StringConverter::toString( m_JumpEnd ) );
                    Ogre::Vector3 distance = m_JumpEnd - m_JumpStart;
                    Ogre::Vector3 pos1, pos2, pos3;
                    pos1.x = m_JumpStart.x + distance.x * 0.25f;
                    pos1.y = m_JumpStart.y + distance.y * 0.25f;
                    float current1 = m_JumpSeconds / 4;
                    pos1.z = current1 * current1 * -13.08f + current1 * ( ( distance.z ) / m_JumpSeconds + m_JumpSeconds * 13.08f ) + m_JumpStart.z;
                    pos2.x = m_JumpStart.x + distance.x * 0.5f;
                    pos2.y = m_JumpStart.y + distance.y * 0.5f;
                    float current2 = current1 * 2;
                    pos2.z = current2 * current2 * -13.08f + current2 * ( ( distance.z ) / m_JumpSeconds + m_JumpSeconds * 13.08f ) + m_JumpStart.z;
                    pos3.x = m_JumpStart.x + distance.x * 0.75f;
                    pos3.y = m_JumpStart.y + distance.y * 0.75f;
                    float current3 = current1 * 3;
                    pos3.z = current3 * current3 * -13.08f + current3 * ( ( distance.z ) / m_JumpSeconds + m_JumpSeconds * 13.08f ) + m_JumpStart.z;
                    DEBUG_DRAW.Line3d( m_JumpStart, pos1 );
                    DEBUG_DRAW.Line3d( pos1, pos2 );
                    DEBUG_DRAW.Line3d( pos2, pos3 );
                    DEBUG_DRAW.Line3d( pos3, m_JumpEnd );
                }
                break;
            }
        }
    }
}
Пример #28
0
// take in a configuration file, find the CSPlugin class associated with the plugname variable, and return an instance
CSPlugin *cs_plugin_load(const char *pluginConfigPath)
{
    ConfigVar cv;

    if (cv.readVar(pluginConfigPath, "=") > 0) {
        if (!is_daemonised) {
            std::cerr << "Unable to load plugin config: " << pluginConfigPath << std::endl;
        }
        syslog(LOG_ERR, "Unable to load plugin config %s", pluginConfigPath);
        return NULL;
    }

    String plugname(cv["plugname"]);
    if (plugname.length() < 1) {
        if (!is_daemonised) {
            std::cerr << "Unable read plugin config plugname variable: " << pluginConfigPath << std::endl;
        }
        syslog(LOG_ERR, "Unable read plugin config plugname variable %s", pluginConfigPath);
        return NULL;
    }

#ifdef ENABLE_CLAMD
    if (plugname == "clamdscan") {
#ifdef DGDEBUG
        std::cout << "Enabling ClamDscan CS plugin" << std::endl;
#endif
        return clamdcreate(cv);
    }
#endif

#ifdef ENABLE_AVASTD
    if (plugname == "avastdscan") {
#ifdef DGDEBUG
        std::cout << "Enabling AvastDscan CS plugin" << std::endl;
#endif
        return avastdcreate(cv);
    }
#endif

#ifdef ENABLE_KAVD
    if (plugname == "kavdscan") {
#ifdef DGDEBUG
        std::cout << "Enabling KAVDscan CS plugin" << std::endl;
#endif
        return kavdcreate(cv);
    }
#endif

#ifdef ENABLE_ICAP
    if (plugname == "icapscan") {
#ifdef DGDEBUG
        std::cout << "Enabling ICAPscan CS plugin" << std::endl;
#endif
        return icapcreate(cv);
    }
#endif

#ifdef ENABLE_COMMANDLINE
    if (plugname == "commandlinescan") {
#ifdef DGDEBUG
        std::cout << "Enabling command-line CS plugin" << std::endl;
#endif
        return commandlinecreate(cv);
    }
#endif

    if (!is_daemonised) {
        std::cerr << "Unable to load plugin: " << pluginConfigPath << std::endl;
    }
    syslog(LOG_ERR, "Unable to load plugin %s\n", pluginConfigPath);
    return NULL;
}
Пример #29
0
static int daemonMain(int argc, char *argv[])
{
    try {
        std::string macAddressString = g_macAddress->val();
        replace(macAddressString, "-", "");
        if (macAddressString.size() != 12u) {
            std::cerr << "MAC address must be 12 characters" << std::endl;
            return -1;
        }
        std::string macAddress = dataFromHexstring(macAddressString);

        std::set<Address::ptr> blacklistedAddresses;
        std::vector<std::string> blacklistedAddressesString = split(
            g_blacklist->val(), ";, ");
        for(std::vector<std::string>::const_iterator it(
            blacklistedAddressesString.begin());
            it != blacklistedAddressesString.end();
            ++it) {
            if(it->empty())
                continue;
            blacklistedAddresses.insert(IPAddress::create(it->c_str()));
        }

        std::vector<std::pair<Address::ptr, unsigned int> > addresses =
            Address::getInterfaceAddresses(g_interface->val(), AF_INET);
        if (addresses.empty()) {
            std::cerr << "Couldn't find interface " << g_interface->val()
                << std::endl;
            return -1;
        }

        IPAddress::ptr localAddress = boost::static_pointer_cast<IPAddress>(
            addresses.front().first);
        IPAddress::ptr broadcastAddress = localAddress->broadcastAddress(
            addresses.front().second);
        broadcastAddress->port(9u);
        IPv4Address multicastAddress("239.255.255.250", 1900);

        IOManager ioManager;

        Socket::ptr broadcastSocket(broadcastAddress->createSocket(ioManager,
            SOCK_DGRAM));
        broadcastSocket->setOption(SOL_SOCKET, SO_BROADCAST, 1);
        broadcastSocket->connect(broadcastAddress);

        Socket::ptr listenSocket(multicastAddress.createSocket(ioManager,
            SOCK_DGRAM));
        listenSocket->setOption(SOL_SOCKET, SO_REUSEADDR, 1);
        listenSocket->bind(IPv4Address(0u, 1900u));
        // TODO: listenSocket->joinGroup(multicastAddress, addresses.front().first);
        struct ip_mreq multicastGroup;
        memcpy(&multicastGroup.imr_multiaddr, &((sockaddr_in *)multicastAddress.name())->sin_addr, sizeof(struct in_addr));
        memcpy(&multicastGroup.imr_interface, &((sockaddr_in *)addresses.front().first->name())->sin_addr, sizeof(struct in_addr));
        listenSocket->setOption(IPPROTO_IP, IP_ADD_MEMBERSHIP, multicastGroup);

        Daemon::onTerminate.connect(boost::bind(&Socket::cancelReceive,
            listenSocket));

        try {
            IPv4Address sender;
            char buffer[4096];
            size_t size;
            while((size = listenSocket->receiveFrom(buffer, 4096, sender))) {
                IPAddress::ptr senderDuplicate = sender.clone();
                senderDuplicate->port(0u);
                if (blacklistedAddresses.find(senderDuplicate) !=
                    blacklistedAddresses.end()) {
                    MORDOR_LOG_VERBOSE(Log::root())
                        << "Skipping broadcast from " << sender;
                    continue;
                }

                HTTP::Request request;
                HTTP::RequestParser parser(request);
                parser.run(buffer, size);
                if (parser.complete() && !parser.error()) {
                    if (request.requestLine.method == "M-SEARCH") {
                        MORDOR_LOG_INFO(Log::root()) << "Relaying M-SEARCH to WOL from "
                            << sender;
                        wol(broadcastSocket, macAddress);
                    }
                } else {
                    MORDOR_LOG_WARNING(Log::root()) << "Unable to parse HTTP request from "
                        << sender << ": " << charslice(buffer, size);
                }
            }
        } catch (OperationAbortedException &) {
        } catch (...) {
            MORDOR_LOG_FATAL(Log::root())
                << boost::current_exception_diagnostic_information();
            return -1;
        }
    } catch (...) {
        std::cerr << boost::current_exception_diagnostic_information() << std::endl;
        return -1;
    }
    return 0;
}
Пример #30
0
namespace Mordor {

static ConfigVar<size_t>::ptr g_defaultBufferSize =
    Config::lookup<size_t>("stream.buffered.defaultbuffersize", 65536,
    "Default buffer size for new BufferedStreams");

static Logger::ptr g_log = Log::lookup("mordor:streams:buffered");

BufferedStream::BufferedStream(Stream::ptr parent, bool own)
: FilterStream(parent, own)
{
    m_bufferSize = g_defaultBufferSize->val();
    m_allowPartialReads = false;
    m_flushMultiplesOfBuffer = false;
}

void
BufferedStream::close(CloseType type)
{
    MORDOR_LOG_VERBOSE(g_log) << this << " close(" << type << ")";
    if (type & READ)
        m_readBuffer.clear();
    try {
        if ((type & WRITE) && m_writeBuffer.readAvailable())
            flush(false);
    } catch (...) {
        if (ownsParent())
            parent()->close(type);
        throw;
    }
    if (ownsParent())
        parent()->close(type);
}

size_t
BufferedStream::read(Buffer &buffer, size_t length)
{
    return readInternal(buffer, length);
}

size_t
BufferedStream::read(void *buffer, size_t length)
{
    return readInternal(buffer, length);
}

// Buffer keeps track of its position automatically
static void advance(Buffer &buffer, size_t amount)
{}

// void * does not
static void advance(void *&buffer, size_t amount)
{
    (unsigned char *&)buffer += amount;
}

template <class T>
size_t
BufferedStream::readInternal(T &buffer, size_t length)
{
    if (supportsSeek())
        flush(false);
    size_t remaining = length;

    size_t buffered = std::min(m_readBuffer.readAvailable(), remaining);
    m_readBuffer.copyOut(buffer, buffered);
    m_readBuffer.consume(buffered);
    remaining -= buffered;

    MORDOR_LOG_VERBOSE(g_log) << this << " read(" << length << "): "
        << buffered << " read from buffer";

    if (remaining == 0)
        return length;

    if (buffered == 0 || !m_allowPartialReads) {
        size_t result;
        do {
            // Read enough to satisfy this request, plus up to a multiple of
            // the buffer size
            size_t todo = ((remaining - 1) / m_bufferSize + 1) * m_bufferSize;
            try {
                MORDOR_LOG_TRACE(g_log) << this << " parent()->read(" << todo
                    << ")";
                result = parent()->read(m_readBuffer, todo);
                MORDOR_LOG_DEBUG(g_log) << this << " parent()->read(" << todo
                    << "): " << result;
            } catch (...) {
                if (remaining == length) {
                    MORDOR_LOG_VERBOSE(g_log) << this << " forwarding exception";
                    throw;
                } else {
                    MORDOR_LOG_VERBOSE(g_log) << this << " swallowing exception";
                    // Swallow the exception
                    return length - remaining;
                }
            }

            buffered = std::min(m_readBuffer.readAvailable(), remaining);
            m_readBuffer.copyOut(buffer, buffered);
            m_readBuffer.consume(buffered);
            advance(buffer, buffered);
            remaining -= buffered;
        } while (remaining > 0 && !m_allowPartialReads && result != 0);
    }

    return length - remaining;
}

size_t
BufferedStream::write(const Buffer &buffer, size_t length)
{
    m_writeBuffer.copyIn(buffer, length);
    size_t result = flushWrite(length);
    // Partial writes not allowed
    MORDOR_ASSERT(result == length);
    return result;
}

size_t
BufferedStream::write(const void *buffer, size_t length)
{
    m_writeBuffer.reserve(std::max(m_bufferSize, length));
    m_writeBuffer.copyIn(buffer, length);
    size_t result = flushWrite(length);
    // Partial writes not allowed
    MORDOR_ASSERT(result == length);
    return result;
}

size_t
BufferedStream::flushWrite(size_t length)
{
    while (m_writeBuffer.readAvailable() >= m_bufferSize)
    {
        size_t result;
        try {
            if (m_readBuffer.readAvailable() && supportsSeek()) {
                parent()->seek(-(long long)m_readBuffer.readAvailable(), CURRENT);
                m_readBuffer.clear();
            }
            size_t toWrite = m_writeBuffer.readAvailable();
            if (m_flushMultiplesOfBuffer)
                toWrite = toWrite / m_bufferSize * m_bufferSize;
            MORDOR_LOG_TRACE(g_log) << this << " parent()->write("
                << m_writeBuffer.readAvailable() << ")";
            result = parent()->write(m_writeBuffer, toWrite);
            MORDOR_LOG_DEBUG(g_log) << this << " parent()->write("
                << m_writeBuffer.readAvailable() << "): " << result;
            m_writeBuffer.consume(result);
        } catch (...) {
            // If this entire write is still in our buffer,
            // back it out and report the error
            if (m_writeBuffer.readAvailable() >= length) {
                MORDOR_LOG_VERBOSE(g_log) << this << " forwarding exception";
                Buffer tempBuffer;
                tempBuffer.copyIn(m_writeBuffer, m_writeBuffer.readAvailable()
                    - length);
                m_writeBuffer.clear();
                m_writeBuffer.copyIn(tempBuffer);
                throw;
            } else {
                // Otherwise we have to say we succeeded,
                // because we're not allowed to have a partial
                // write, and we can't report an error because
                // the caller will think he needs to repeat
                // the entire write
                MORDOR_LOG_VERBOSE(g_log) << this << " swallowing exception";
                return length;
            }
        }
    }
    return length;
}

long long
BufferedStream::seek(long long offset, Anchor anchor)
{
    MORDOR_ASSERT(parent()->supportsTell());
    long long parentPos = parent()->tell();
    long long bufferedPos = parentPos - m_readBuffer.readAvailable()
        + m_writeBuffer.readAvailable();
    long long parentSize = parent()->supportsSize() ? -1ll : parent()->size();
    // Check for no change in position
    if ((offset == 0 && anchor == CURRENT) ||
        (offset == bufferedPos && anchor == BEGIN) ||
        (parentSize != -1ll && offset + parentSize == bufferedPos &&
        anchor == END))
        return bufferedPos;

    MORDOR_ASSERT(supportsSeek());
    flush(false);
    MORDOR_ASSERT(m_writeBuffer.readAvailable() == 0u);
    switch (anchor) {
        case BEGIN:
            MORDOR_ASSERT(offset >= 0);
            if (offset >= bufferedPos && offset <= parentPos) {
                m_readBuffer.consume((size_t)(offset - bufferedPos));
                return offset;
            }
            m_readBuffer.clear();
            break;
        case CURRENT:
            if (offset > 0 && offset <= (long long)m_readBuffer.readAvailable()) {
                m_readBuffer.consume((size_t)offset);
                return bufferedPos + offset;
            }
            offset -= m_readBuffer.readAvailable();
            m_readBuffer.clear();
            break;
        case END:
            if (parentSize == -1ll)
                throw std::invalid_argument("Can't seek from end without known size");
            if (parentSize + offset >= bufferedPos && parentSize + offset <= parentPos) {
                m_readBuffer.consume((size_t)(parentSize + offset - bufferedPos));
                return parentSize + offset;
            }
            m_readBuffer.clear();
            break;
        default:
            MORDOR_NOTREACHED();
    }
    return parent()->seek(offset, anchor);
}

long long
BufferedStream::size()
{
    long long size = parent()->size();
    if (parent()->supportsTell()) {
        return std::max(size, tell());
    } else {
        // not a seekable stream; we can only write to the end
        size += m_writeBuffer.readAvailable();
    }
    return size;
}

void
BufferedStream::truncate(long long size)
{
    if (!parent()->supportsTell() ||
        parent()->tell() + (long long)m_writeBuffer.readAvailable() >= size)
        flush(false);
    // TODO: truncate/clear m_readBuffer only if necessary
    m_readBuffer.clear();
    parent()->truncate(size);
}

void
BufferedStream::flush(bool flushParent)
{
    while (m_writeBuffer.readAvailable()) {
        if (m_readBuffer.readAvailable() && supportsSeek()) {
            parent()->seek(-(long long)m_readBuffer.readAvailable(), CURRENT);
            m_readBuffer.clear();
        }
        MORDOR_LOG_TRACE(g_log) << this << " parent()->write("
            << m_writeBuffer.readAvailable() << ")";
        size_t result = parent()->write(m_writeBuffer, m_writeBuffer.readAvailable());
        MORDOR_LOG_DEBUG(g_log) << this << " parent()->write("
            << m_writeBuffer.readAvailable() << "): " << result;
        MORDOR_ASSERT(result > 0);
        m_writeBuffer.consume(result);
    }
    if (flushParent)
        parent()->flush();
}

ptrdiff_t
BufferedStream::find(char delim, size_t sanitySize, bool throwIfNotFound)
{
    if (supportsSeek())
        flush(false);
    if (sanitySize == (size_t)~0)
        sanitySize = 2 * m_bufferSize;
    ++sanitySize;
    while (true) {
        size_t readAvailable = m_readBuffer.readAvailable();
        if (readAvailable > 0) {
            ptrdiff_t result = m_readBuffer.find(delim, std::min(sanitySize, readAvailable));
            if (result != -1) {
                return result;
            }
        }
        if (readAvailable >= sanitySize) {
            if (throwIfNotFound)
                MORDOR_THROW_EXCEPTION(BufferOverflowException());
            return -(ptrdiff_t)m_readBuffer.readAvailable() - 1;
        }

        MORDOR_LOG_TRACE(g_log) << this << " parent()->read(" << m_bufferSize
            << ")";
        size_t result = parent()->read(m_readBuffer, m_bufferSize);
        MORDOR_LOG_DEBUG(g_log) << this << " parent()->read(" << m_bufferSize
            << "): " << result;
        if (result == 0) {
            // EOF
            if (throwIfNotFound)
                MORDOR_THROW_EXCEPTION(UnexpectedEofException());
            return -(ptrdiff_t)m_readBuffer.readAvailable() - 1;
        }
    }
}

ptrdiff_t
BufferedStream::find(const std::string &str, size_t sanitySize, bool throwIfNotFound)
{
    if (supportsSeek())
        flush(false);
    if (sanitySize == (size_t)~0)
        sanitySize = 2 * m_bufferSize;
    sanitySize += str.size();
    while (true) {
        size_t readAvailable = m_readBuffer.readAvailable();
        if (readAvailable > 0) {
            ptrdiff_t result = m_readBuffer.find(str, std::min(sanitySize, readAvailable));
            if (result != -1) {
                return result;
            }
        }
        if (readAvailable >= sanitySize) {
            if (throwIfNotFound)
                MORDOR_THROW_EXCEPTION(BufferOverflowException());
            return -(ptrdiff_t)m_readBuffer.readAvailable() - 1;
        }

        MORDOR_LOG_TRACE(g_log) << this << " parent()->read(" << m_bufferSize
            << ")";
        size_t result = parent()->read(m_readBuffer, m_bufferSize);
        MORDOR_LOG_DEBUG(g_log) << this << " parent()->read(" << m_bufferSize
            << "): " << result;
        if (result == 0) {
            // EOF
            if (throwIfNotFound)
                MORDOR_THROW_EXCEPTION(UnexpectedEofException());
            return -(ptrdiff_t)m_readBuffer.readAvailable() - 1;
        }
    }
}

void
BufferedStream::unread(const Buffer &b, size_t len)
{
    MORDOR_ASSERT(supportsUnread());
    Buffer tempBuffer;
    tempBuffer.copyIn(b, len);
    tempBuffer.copyIn(m_readBuffer);
    m_readBuffer.clear();
    m_readBuffer.copyIn(tempBuffer);
}

}