标签:
***************************************************************************************************************************
作者:EasyWave 时间:2015.01.11
类别:路由器类-基于RTL819X实现的Router/AP的源码分析[一] 声明:转载,请保留链接
注意:如有错误,欢迎指正。这些是我学习的日志文章......
***************************************************************************************************************************
一:基于RT819X平台的深度定制化BOA简介详细的关于BOA的介绍,请参考我的博文:嵌入式Linux下BOA网页服务器的移植的详细介绍,BOA WebServer是一款单任务的HTTP服务器,与其他网页服务器不同之处,是当有连接请求到来是,它既不是为每个连接都单独创建进程,也不是采用复制自身进程处理多链接,而是通过建立HTTP请求列表来处理多路HTTP连接请求,同时它只为CGI程序创建新的简称,在最大程度上节省了系统资源,这对于资源受限的嵌入式系统来说非常重要,同时它还自动生成目录、自动解压文件等功能,因此BOA具有很高的HTTP请求处理速度和效率,应用在嵌入式系统中具有很高的价值。
基于RT819x平台的Router/AP是构建在开源的BOA Web服务器上的,通过进入BOA的目录中,可以发现RT819x平台的Router/AP是在BOA开源代码上深度定制化的,具体的情况如下所示:
跟开源的BOA Web服务器多了很多文件夹,这是因为基于RT819x实现的Router/AP在开源的BOA基础上增加了一个ASP服务器,同时也实现了一个微型的小网站服务器,微型网站的代码如下所示:
这个是整个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中调用的。如下所示:
图一:asp_page.c中的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)函数调用
而在boa.c中的main函数中就会调用void loop(int server_s)函数,如下所示:
分析到这里大概知道BOA对于ASP命令的解析的基本流程了,那么我们采用一个实例命令来分析一下void handleForm(request *req)是如何处理html页面中的命令的,在boa/html/syscmd.htm中打开syscmd.htm的代码,如下所示:
在上述代码中可以看到<form action=/boafrm/formSysCmd method=POST name="formSysCmd">这行代码,我们就从这行代码来分析吧,我们先来看看void handleForm(request *req)函数吧,如下所示:
从中我们可以看到root_form这个table,而#define SCRIPT_ALIAS "/boafrm/"被定义为boafrm,那么从刚刚的那行代码中我们可以看到在/boafrm/formSysCmd中会执行formSysCmd函数的,而这个函数就在root_form这个table中,如下所示:
这篇博文简单的分析深度定制化的BOA下的ASP服务器命令的处理流程,详细的介绍后续会继续更新到博客上,这是本人学习的一些总结,在学习过程中肯定会有这样那样的错误,但是这就是一个学习的过程。
标签:
原文地址:http://blog.csdn.net/wavemcu/article/details/42611109