• igmpproxy源代码学习——配置信息加载 loadConfig




            在igmpproxy主程序运行之前需要先读取配置文件,igmpproxy的配置文件通常为/etc/igmpproxy.conf或者/var/igmpproxy.conf
    其内容如下:
    quickleave
    mode 3
    phyint ppp0 upstream  ratelimit 0  threshold 1
    phyint br0 downstream  ratelimit 0  threshold 1


            igmpproxy加载配置文件信息由main函数中调用loadConfig()实现,加载配置文件的代码主要在config.c中。在分析loadConfig的具体实现之前,我们先了解config.c中的结构体struct vifconfig。该结构体记录了关于igmpproxy端口等配置信息。
    struct vifconfig {
        char*	name;		//端口名称 如eth0
        short	state;		//端口状态  0-无效端口  1
        int		ratelimit;	//访问速率的限制值
        int		threshold;	//TTl阈值
        // Keep allowed nets for VIF.
        struct SubnetList*  allowednets;	//关于子网IP地址及子网掩码的结构体
        
        // Next config in list...
        struct vifconfig*   next;	//下一个节点
    };


            在config.c中,定义了struct vifconfig的全局变量vifconf。这个全局变量保存了我们从配置文件中读取的配置信息。laodConfig()的主要作用就是讲配置文件中的信息记录了通过vifconf可以访问的链表中。然后main函数在调用igmpProxyInit(),该函数访问vifconf,进行相关配置。当然igmpProxyInit()还有其他作用。
        
        

    loadConfig

        接下来我们进入loadConfig了解配置信息加载的主要流程。
    void initCommonConfig()
        loadConfig首先调用initCommonConfig()函数,初始化一些公共常量
    openConfigFile(configFile)
        打开配置文件,容易理解。除了打开配置文件外,这个函数还为全局指针变量iBuffer分配内存空间。iBuffer用于保存每次从配置文件中读取的512个字节的内容。igmpproxy的加载配置信息的实现是:每次从配置文件中至多读取512字节(实际上可能是一行一行读)的数据放在IBuffer中,然后再从iBuffer中解析出每一个token(关于iBuffer在nextConfigToken()会更详细的解释)。
    nextConfigToken()
        顾名思义,nextConfigToken()的作用是从igmpproxy.conf中解析出一个一个token。但是它不是每一个token都去访问一次igmpproxy.conf的,而是一次性取出READ_BUFFER_SIZE大小的数据放在缓冲区iBuffer中,然后再从iBuffer中一个词一个词解析,这512字节解析完了遇到''的时候,(bufPtr == readSize)为真,再fread出512字节的数据。
        如果igmpproxy.conf读完了,且读出来的数据都在nextConfigToken中解析完了,则(readSize < READ_BUFFER_SIZE && bufPtr == readSize)为真,这时返回NULL。
        因为nextConfigToken()使用了缓冲区iBuffer,它就不是每一次运行都去访问一次igmpproxy.conf。第一次运行nextConfigToken的时候我们必须执行fread从次igmpproxy.conf中读取512字节的数据,第二次执行nextConfigToken的时候,因为我们第一次读出来放在iBuffer中的数据还没有用完,就不需要在fread一次了。
    loadConfig的核心流程  
            loadConfig()函数中,在第一次执行nextConfigToken获取一个token后,我们就进入了loadConfig的核心流程,也就是配置信息的解析以及将配置信息解析为结构体struct vifconfig的成员变量保存在全局变量vifconf中(如端口信息,IP地址等等)。
        正确的配置文件可能包含三类信息(不一定三类都有),分别是phyint、quickleave和mode。loadConfig通过token与这三个词的匹配来判断要进行什么样的处理。(我下载的官方源码是不支持mode的,这可以通过自己修改源码实现,我们也可以再配置文件igmpproxy.conf中写入其他配置信息,然后再loadConfig增加处理方法)
        如果发现当前读取到的是有关phyint的信息,则调用parsePhyintToken()按照phyint的规则解析,将信息已结构体struct vifconfig的形式保存给指针tmpPtr,再通过currPtr串到vifconf中。关于parsePhyintToken后面有做说明。
            如果发现当前读取到的是quickleave,则写到公共配置中commonConfig.fastUpstreamLeave = 1;
    parsePhyintToken
            首先看返回值,是一个struct vifconfig 类型的结构体指针。
            在刚刚进入 parsePhyintToken时,token必须是网络接口的名字如(eth0,ppp0,br0),因此第一个token大小不能超过sizeof( ((struct ifreq *)NULL)->ifr_name)。接下来对结构体指针tmpPtr的成员变量进行初始化 。
        tmpPtr->next = NULL;    // Important to avoid seg fault...
        tmpPtr->ratelimit = 0;
        tmpPtr->threshold = 1;
        tmpPtr->state = IF_STATE_DOWNSTREAM;
        tmpPtr->allowednets = NULL


            初始化完成后,将token(此时为接口名称)拷贝给tmpPtr->name
     strcpy(tmpPtr->name, token);
            然后使用altnet、upstream等关键词逐个匹配后面的token。匹配到altnet是需要使用parseSubnetAddress进一步解析:
      *anetPtr = parseSubnetAddress(token);

            匹配到upstream、downstream、disabled、ratelimit、threshold时直接对tmpPtr的成员变量进行设置。如:
          else if(strcmp("upstream", token)==0) {
                // Upstream
                IF_DEBUG log(LOG_DEBUG, 0, "Config: IF: Got upstream token.");
                tmpPtr->state = IF_STATE_UPSTREAM;
            

    parseSubnetAddress
           将 a.b.c.d/n格式的子网IP解析为结构体struct SubnetList
    struct SubnetList {
        uint32              subnet_addr;
        uint32              subnet_mask;
        struct SubnetList*  next;
    }

    getCurrentConfigToken
        判断token是否合法,没什么好解释的。


    总结:

        loadConfig主循环。
    nextConfigToken()
    while(){
        phyint:
            parsePhyintToken()
        quickleave/mode:
            直接修改公共配置
    }

    parsePhyintToken 将phyint的信息通过一个链表保存在vifconf中。 







  • 相关阅读:
    耗时很长的服务器端事件中让客户端得到中间过程信息的合理解决方案(续)
    复杂一点的查询
    耗时很长的服务器端事件中让客户端得到中间过程信息的合理解决方案
    PET SHOP 4.0 初学者分析(项目分解)
    TSQL学习笔记(索引贴)
    存储过程和用户自定义函数
    c#简单的音乐播放器,支持多种格式,可扩展性强
    图片的无级缩放和无级截取(js+.net)
    在线部署web项目(适用于较大型项目)
    约束
  • 原文地址:https://www.cnblogs.com/Windeal/p/4284639.html
Copyright © 2020-2023  润新知