[置顶] 基于RTL819X实现的Router/AP的源码分析[一]

***************************************************************************************************************************
作者:EasyWave                                                                               时间:2015.01.11

类别:路由器类-基于RTL819X实现的Router/AP的源码分析[一]    声明:转载,请保留链接

注意:如有错误,欢迎指正。这些是我学习的日志文章...... [交流群 : 27016614]

***************************************************************************************************************************

一:基于RT819X平台的深度定制化BOA简介

       详细的关于BOA的介绍,请参考我的博文:嵌入式Linux下BOA网页服务器的移植的详细介绍,BOA WebServer是一款单任务的HTTP服务器,与其他网页服务器不同之处,是当有连接请求到来是,它既不是为每个连接都单独创建进程,也不是采用复制自身进程处理多链接,而是通过建立HTTP请求列表来处理多路HTTP连接请求,同时它只为CGI程序创建新的简称,在最大程度上节省了系统资源,这对于资源受限的嵌入式系统来说非常重要,同时它还自动生成目录、自动解压文件等功能,因此BOA具有很高的HTTP请求处理速度和效率,应用在嵌入式系统中具有很高的价值。

二:基于RT819X平台的深度定制化BOA源码分析

        基于RT819x平台的Router/AP是构建在开源的BOA Web服务器上的,通过进入BOA的目录中,可以发现RT819x平台的Router/AP是在BOA开源代码上深度定制化的,具体的情况如下所示:

[置顶] 基于RTL819X实现的Router/AP的源码分析[一]_第1张图片

        跟开源的BOA Web服务器多了很多文件夹,这是因为基于RT819x实现的Router/AP在开源的BOA基础上增加了一个ASP服务器,同时也实现了一个微型的小网站服务器,微型网站的代码如下所示:

[置顶] 基于RTL819X实现的Router/AP的源码分析[一]_第2张图片

        这个是整个Router/AP前台的设置页面配置微型网站,这个跟我们自己家里用的Router,比如需要输入http://192.168.1.1这样进入页面设置的作用是一样的,所有的设置都是在html文件夹中实现的,由于开源的BOA并不支持ASP服务器,因此需要对BOA代码进行深度定制化,我们来看看RT819X是如何实现的呢?我们还是先来分析BOA的入口main函数吧,在users/boa/src/boa.c文件中,如下所示:

int main(int argc, char *argv[])
{
    int server_s;               /* boa socket */
    pid_t pid;

    /* set umask to u+rw, u-x, go-rwx */
    /* according to the man page, umask always succeeds */
    umask(077);

    /* but first, update timestamp, because log_error_time uses it */
    (void) time(¤t_time);

    /* set timezone right away */
    tzset();

    {
        int devnullfd = -1;
        devnullfd = open("/dev/null", 0);

        /* make STDIN point to /dev/null */
        if (devnullfd == -1) {
            DIE("can't open /dev/null");
        }

        if (dup2(devnullfd, STDIN_FILENO) == -1) {
            DIE("can't dup2 /dev/null to STDIN_FILENO");
        }

        (void) close(devnullfd);
    }

    parse_commandline(argc, argv);
    fixup_server_root();

#ifdef SUPPORT_ASP
	extern void asp_init(int argc,char **argv); // davidhsu
	asp_init(argc,argv);
#ifdef VOIP_SUPPORT
	web_voip_init();
#endif 
#endif

    read_config_files();
    create_common_env();
    open_logs();
    server_s = create_server_socket();
    //init_signals(); //Brad comment out, move to later 
    build_needs_escape();

    /* background ourself */
    if (do_fork) {
        pid = fork();
    } else {
        pid = getpid();
    }

    switch (pid) {
    case -1:
        /* error */
        perror("fork/getpid");
        exit(EXIT_FAILURE);
    case 0:
        /* child, success */
        break;
    default:
        /* parent, success */
        if (pid_file != NULL) {
            FILE *PID_FILE = fopen(pid_file, "w");
            if (PID_FILE != NULL) {
                fprintf(PID_FILE, "%d\n", pid);
                fclose(PID_FILE);
            } else {
                perror("fopen pid file");
            }
        }

        if (do_fork)
            exit(EXIT_SUCCESS);
        break;
    }

    boa_start = 1;
    init_signals(); //Brad move here
    drop_privs();
    /* main loop */
    timestamp();

    status.requests = 0;
    status.errors = 0;

    start_time = current_time;
    alarm(1);
    loop(server_s);
    return 0;
}
     我们把上面中的宏定义SUPPORT_ASP单独拿出来看看,如下所示:

#ifdef SUPPORT_ASP

extern void asp_init(int argc,char **argv); // davidhsu

asp_init(argc,argv);

#ifdef VOIP_SUPPORT

web_voip_init();

#endif 

#endif

       这样我们看到,RT819X实现的Router/AP是在开源BOA的基础上定制化了一个ASP的服务器,进入asp_init(argc,argv)函数中去看看,在users/boa/src/asp_page.c中,如下所示:

void asp_init(int argc,char **argv)
{
	int i, num;
	char interface[10];
	extern int getWlStaNum(char *interface, int *num);

	root_temp.next=NULL;
	root_temp.str=NULL;	
	
	// david ---- queury number of wlan interface ----------------
	wlan_num = 0;
	for (i=0; i<NUM_WLAN_INTERFACE; i++) {
		sprintf(interface, "wlan%d", i);
		if (getWlStaNum(interface, &num) < 0)
			break;
		wlan_num++;
	}
	
#if defined(VOIP_SUPPORT) && defined(ATA867x)
	// no wlan interface in ATA867x
#else
	if (wlan_num==0)
		wlan_num = 1;	// set 1 as default
#endif

#ifdef MBSSID
	vwlan_num = NUM_VWLAN_INTERFACE; 
#endif
	//---------------------------------------------------------

//conti:
	root_temp.next = NULL;
	root_temp.str = NULL;	

	if (apmib_init() == 0) {
		printf("Initialize AP MIB failed!\n");
		return;
	}

	save_cs_to_file();
	apmib_get(MIB_WAN_DHCP, (void *)&last_wantype);

	/* determine interface name by mib value */
	WAN_IF = "eth1";
	BRIDGE_IF = "br0";
	ELAN_IF = "eth0";
	ELAN2_IF = "eth2";
	ELAN3_IF = "eth3";
	ELAN4_IF = "eth4";

#ifdef HOME_GATEWAY
	PPPOE_IF = "ppp0";
#elif defined(VOIP_SUPPORT) && defined(ATA867x)
	BRIDGE_IF = "eth0";
	ELAN_IF = "eth0";
#else
	BRIDGE_IF = "br0";
	ELAN_IF = "eth0";
#endif
	strcpy(WLAN_IF,"wlan0");
	//---------------------------

	query_temp_var = (char *)malloc(MAX_QUERY_TEMP_VAL_SIZE);
	if (query_temp_var==NULL)
		exit(0);
	return;
	
//main_end:
	//shmdt(pRomeCfgParam);
	exit(0);
}
     这个函数是asp服务器的核心代码,注意这是一个深度定制化的ASP服务器,整个ASP服务器的分发和处理是在void handleForm(request *req)处理的,这个void handleForm(request *req)函数是由get.c中的int init_form(request * req)函数调用,而int init_form(request * req)函数是被read.c中的int write_body(request * req)函数调用的,而int write_body(request * req)函数是被request.c中的void process_requests(int server_sock)函数调用的,而void process_requests(int server_sock)函数是被poll.c或者select.c中的void loop(int server_s)函数调用的,而void loop(int server_s)函数是被boa.c中调用的。如下所示:

[置顶] 基于RTL819X实现的Router/AP的源码分析[一]_第3张图片

图一:asp_page.c中的void handleForm(request *req)函数

[置顶] 基于RTL819X实现的Router/AP的源码分析[一]_第4张图片

图二:void handleForm(request *req)函数是由get.c中的int init_form(request * req)函数调用

[置顶] 基于RTL819X实现的Router/AP的源码分析[一]_第5张图片

图三:int init_form(request * req)函数是被read.c中的int write_body(request * req)

[置顶] 基于RTL819X实现的Router/AP的源码分析[一]_第6张图片

图四:int write_body(request * req)函数是被request.c中的void process_requests(int server_sock)函数调用

[置顶] 基于RTL819X实现的Router/AP的源码分析[一]_第7张图片

图五:void process_requests(int server_sock)函数是被poll.c或者select.c中的void loop(int server_s)函数调用

      而在boa.c中的main函数中就会调用void loop(int server_s)函数,如下所示:

[置顶] 基于RTL819X实现的Router/AP的源码分析[一]_第8张图片

       分析到这里大概知道BOA对于ASP命令的解析的基本流程了,那么我们采用一个实例命令来分析一下void handleForm(request *req)是如何处理html页面中的命令的,在boa/html/syscmd.htm中打开syscmd.htm的代码,如下所示:

[置顶] 基于RTL819X实现的Router/AP的源码分析[一]_第9张图片

       在上述代码中可以看到<form action=/boafrm/formSysCmd method=POST name="formSysCmd">这行代码,我们就从这行代码来分析吧,我们先来看看void handleForm(request *req)函数吧,如下所示:

[置顶] 基于RTL819X实现的Router/AP的源码分析[一]_第10张图片

      从中我们可以看到root_form这个table,而#define SCRIPT_ALIAS "/boafrm/"被定义为boafrm,那么从刚刚的那行代码中我们可以看到在/boafrm/formSysCmd中会执行formSysCmd函数的,而这个函数就在root_form这个table中,如下所示:

[置顶] 基于RTL819X实现的Router/AP的源码分析[一]_第11张图片


三:基于RT819X平台的深度定制化BOA源码总结

     这篇博文简单的分析深度定制化的BOA下的ASP服务器命令的处理流程,详细的介绍后续会继续更新到博客上,这是本人学习的一些总结,在学习过程中肯定会有这样那样的错误,但是这就是一个学习的过程。

你可能感兴趣的:([置顶] 基于RTL819X实现的Router/AP的源码分析[一])