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

在igmpproxy主程序运行之前需要先读取配置文件,igmpproxy的配置文件通常为/etc/igmpproxy.conf或者/var/igmpproxy.conf

其内容如下:

  1. quickleave
  2. mode 3
  3. phyint ppp0 upstream ratelimit 0 threshold 1
  4. phyint br0 downstream ratelimit 0 threshold 1

igmpproxy加载配置文件信息由main函数中调用loadConfig()实现,加载配置文件的代码主要在config.c中。在分析loadConfig的具体实现之前,我们先了解config.c中的结构体struct
vifconfig。该结构体记录了关于igmpproxy端口等配置信息。

  1. struct vifconfig {
  2. char* name; //端口名称 如eth0
  3. short state; //端口状态 0-无效端口 1
  4. int ratelimit; //访问速率的限制值
  5. int threshold; //TTl阈值
  6. // Keep allowed nets for VIF.
  7. struct SubnetList* allowednets; //关于子网IP地址及子网掩码的结构体
  8. // Next config in list...
  9. struct vifconfig* next; //下一个节点
  10. };

在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字节解析完了遇到‘\0‘的时候,(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的成员变量进行初始化 。

  1. tmpPtr->next = NULL; // Important to avoid seg fault...
  2. tmpPtr->ratelimit = 0;
  3. tmpPtr->threshold = 1;
  4. tmpPtr->state = IF_STATE_DOWNSTREAM;
  5. tmpPtr->allowednets = NULL

初始化完成后,将token(此时为接口名称)拷贝给tmpPtr->name

  1.  strcpy(tmpPtr->name, token);

然后使用altnet、upstream等关键词逐个匹配后面的token。匹配到altnet是需要使用parseSubnetAddress进一步解析:

  1. *anetPtr = parseSubnetAddress(token);

匹配到upstream、downstream、disabled、ratelimit、threshold时直接对tmpPtr的成员变量进行设置。如:

  1. else if(strcmp("upstream", token)==0) {
  2. // Upstream
  3. IF_DEBUG log(LOG_DEBUG, 0, "Config: IF: Got upstream token.");
  4. tmpPtr->state = IF_STATE_UPSTREAM;

parseSubnetAddress

将 a.b.c.d/n格式的子网IP解析为结构体struct
SubnetList

  1. struct SubnetList {
  2. uint32 subnet_addr;
  3. uint32 subnet_mask;
  4. struct SubnetList* next;
  5. }

getCurrentConfigToken

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

总结:

    loadConfig主循环。

  1. nextConfigToken()
  2. while(){
  3. phyint:
  4. parsePhyintToken()
  5. quickleave/mode:
  6. 直接修改公共配置
  7. }

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

时间: 2024-11-05 05:26:43

igmpproxy源代码学习——配置信息加载的相关文章

igmpproxy源代码学习——igmpProxyInit()

igmpproxy源代码学习--igmpProxyInit()函数详解,igmpproxy初始化 在运行igmpproxy的主程序igmpproxyRun()之前需要对igmpproxy进行一些配置,这些配置都是在igmpProxyInit()中完成的. 要进行的配置主要有: 信号处理配置 物理网络接口配置加载 配置文件的加载 虚拟网络设备初始化 路由向量表初始化 定时器初始化 信号处理配置 首先进行信号处理配置: sigemptyset(&sa.sa_mask); sigaction(SIGT

OGEngine学习笔记---资源加载

声音管理兼容各种音频文件格式,比特率和样本率 OGEngine开源引擎兼容各种音频视频文件格式,并且引用了硬件加速技术,来对音频文件进行io读取,简化了资源的加载和读取写入的过程,大幅度减少应用卡顿.无响应的状况出现. 一个背景音乐 多个音效 OGEngine开源引擎在同一时间只能播放一首背景音乐,但是能同时播放多个音效. 首先自定义一个枚举类ConfigData,用来存放背景音乐key和音效key. public class ConfigData { /** 背景音乐*/ public sta

Away3D 学习笔记(一): 加载3DS格式的模型文件

加载外部的3DS文件分为两种: 1: 模型与贴图独立于程序的,也就是从外部的文件夹中读取 1 private function load3DSFile():Loader3D 2 { 3 loader = new Loader3D(); 4 loader.addEventListener(LoaderEvent.RESOURCE_COMPLETE,onLoadComplete); 5 loader.addEventListener(AssetEvent.ASSET_COMPLETE,onAsset

HTML5的学习--performance获取加载时间的工具

前段时间因为项目需要获取页面加载的时间,就去看了下HTML5中的performane. 可以用其获得页面详细的加载时间. 关于performance的详细内容可以查看 http://www.cnblogs.com/CraryPrimitiveMan/p/3795086.html 之后用performane写了一个小工具,用来获取页面详细的加载时间. GitHub上的地址是:https://github.com/CraryPrimitiveMan/performance-tool 只在chrome

深入java虚拟机学习 -- 类的加载机制(续)

昨晚写 深入java虚拟机学习 -- 类的加载机制 都到1点半了,由于第二天还要工作,没有将上篇文章中的demo讲解写出来,今天抽时间补上昨晚的例子讲解. 这里我先把昨天的两份代码贴过来,重新看下: class Singleton { private static Singleton singleton = new Singleton(); //第一份代码的位置 public static int counter1; public static int counter2=0; private s

Spring集成JPA配置懒加载两个报错解决办法

一:报错no session 因为entitymanager对象在事物提交后就关闭了 报错的 no session相当于sql的session 解决办法:解决办法 在web.xmL配置一个过滤器 使其在这个session中的manager在结束后再关闭open <!--配置openmanager--> <filter> <filter-name>openEntity</filter-name> <filter-class>org.springfr

log4j.properties配置与加载应用

log4j.properties总结: 一.介绍 Log4j是Apache的一个开放源代码项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台.文件.GUI组件.甚至是套接口服务 器.NT的事件记录器.UNIX Syslog守护进程等:我们也可以控制每一条日志的输出格式:通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程. Log4j由三个重要的组件构成:日志信息的优先级,日志信息的输出目的地,日志信息的输出格式.日志信息的优先级从高到低有ERROR.WARN. I

Spring Cloud Alibaba基础教程:Nacos配置的加载规则详解

前情回顾: <Spring Cloud Alibaba基础教程:使用Nacos实现服务注册与发现> <Spring Cloud Alibaba基础教程:支持的几种服务消费方式(RestTemplate.WebClient.Feign)> <Spring Cloud Alibaba基础教程:使用Nacos作为配置中心> 上一篇,我们学习了如何在Nacos中创建配置,以及如何使用Spring Cloud Alibaba的Nacos客户端模块来加载配置.在入门例子中,我们只配

服务器启动时Webapp的web.xml中配置的加载顺序

一 1.启动一个WEB项目的时候,WEB容器会去读取它的配置文件web.xml,读取<listener>和<context-param>两个结点. 2.紧急着,容创建一个ServletContext(servlet上下文),这个web项目的所有部分都将共享这个上下文. 3.容器将<context-param>转换为键值对,并交给servletContext. 4.容器创建<listener>中的类实例,创建监听器. 二  Load-on-startup Lo